Diff of the two buildlogs: -- --- b1/build.log 2025-02-22 07:41:52.648287146 +0000 +++ b2/build.log 2025-02-22 07:44:32.365067184 +0000 @@ -1,6 +1,6 @@ I: pbuilder: network access will be disabled during build -I: Current time: Fri Mar 27 02:02:10 -12 2026 -I: pbuilder-time-stamp: 1774620130 +I: Current time: Sat Feb 22 21:41:54 +14 2025 +I: pbuilder-time-stamp: 1740210114 I: Building the build Environment I: extracting base tarball [/var/cache/pbuilder/unstable-reproducible-base.tgz] I: copying local configuration @@ -22,52 +22,84 @@ dpkg-source: info: unpacking python-sse-starlette_2.2.1-1.debian.tar.xz I: Not using root during the build. I: Installing the build-deps -I: user script /srv/workspace/pbuilder/957030/tmp/hooks/D02_print_environment starting +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/D01_modify_environment starting +debug: Running on ionos1-amd64. +I: Changing host+domainname to test build reproducibility +I: Adding a custom variable just for the fun of it... +I: Changing /bin/sh to bash +'/bin/sh' -> '/bin/bash' +lrwxrwxrwx 1 root root 9 Feb 22 07:42 /bin/sh -> /bin/bash +I: Setting pbuilder2's login shell to /bin/bash +I: Setting pbuilder2's GECOS to second user,second room,second work-phone,second home-phone,second other +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/D01_modify_environment finished +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/D02_print_environment starting I: set - BUILDDIR='/build/reproducible-path' - BUILDUSERGECOS='first user,first room,first work-phone,first home-phone,first other' - BUILDUSERNAME='pbuilder1' - BUILD_ARCH='amd64' - DEBIAN_FRONTEND='noninteractive' - DEB_BUILD_OPTIONS='buildinfo=+all reproducible=+all parallel=42 ' - DISTRIBUTION='unstable' - HOME='/root' - HOST_ARCH='amd64' + BASH=/bin/sh + BASHOPTS=checkwinsize:cmdhist:complete_fullquote:extquote:force_fignore:globasciiranges:globskipdots:hostcomplete:interactive_comments:patsub_replacement:progcomp:promptvars:sourcepath + BASH_ALIASES=() + BASH_ARGC=() + BASH_ARGV=() + BASH_CMDS=() + BASH_LINENO=([0]="12" [1]="0") + BASH_LOADABLES_PATH=/usr/local/lib/bash:/usr/lib/bash:/opt/local/lib/bash:/usr/pkg/lib/bash:/opt/pkg/lib/bash:. + BASH_SOURCE=([0]="/tmp/hooks/D02_print_environment" [1]="/tmp/hooks/D02_print_environment") + BASH_VERSINFO=([0]="5" [1]="2" [2]="37" [3]="1" [4]="release" [5]="x86_64-pc-linux-gnu") + BASH_VERSION='5.2.37(1)-release' + BUILDDIR=/build/reproducible-path + BUILDUSERGECOS='second user,second room,second work-phone,second home-phone,second other' + BUILDUSERNAME=pbuilder2 + BUILD_ARCH=amd64 + DEBIAN_FRONTEND=noninteractive + DEB_BUILD_OPTIONS='buildinfo=+all reproducible=+all parallel=20 ' + DIRSTACK=() + DISTRIBUTION=unstable + EUID=0 + FUNCNAME=([0]="Echo" [1]="main") + GROUPS=() + HOME=/root + HOSTNAME=i-capture-the-hostname + HOSTTYPE=x86_64 + HOST_ARCH=amd64 IFS=' ' - INVOCATION_ID='edf4ae20339d48e8853c5d9518aac51c' - LANG='C' - LANGUAGE='en_US:en' - LC_ALL='C' - MAIL='/var/mail/root' - OPTIND='1' - PATH='/usr/sbin:/usr/bin:/sbin:/bin:/usr/games' - PBCURRENTCOMMANDLINEOPERATION='build' - PBUILDER_OPERATION='build' - PBUILDER_PKGDATADIR='/usr/share/pbuilder' - PBUILDER_PKGLIBDIR='/usr/lib/pbuilder' - PBUILDER_SYSCONFDIR='/etc' - PPID='957030' - PS1='# ' - PS2='> ' + INVOCATION_ID=a4508a0288184089a1c4e8edccdc6249 + LANG=C + LANGUAGE=et_EE:et + LC_ALL=C + MACHTYPE=x86_64-pc-linux-gnu + MAIL=/var/mail/root + OPTERR=1 + OPTIND=1 + OSTYPE=linux-gnu + PATH=/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path + PBCURRENTCOMMANDLINEOPERATION=build + PBUILDER_OPERATION=build + PBUILDER_PKGDATADIR=/usr/share/pbuilder + PBUILDER_PKGLIBDIR=/usr/lib/pbuilder + PBUILDER_SYSCONFDIR=/etc + PIPESTATUS=([0]="0") + POSIXLY_CORRECT=y + PPID=1539955 PS4='+ ' - PWD='/' - SHELL='/bin/bash' - SHLVL='2' - SUDO_COMMAND='/usr/bin/timeout -k 18.1h 18h /usr/bin/ionice -c 3 /usr/bin/nice /usr/sbin/pbuilder --build --configfile /srv/reproducible-results/rbuild-debian/r-b-build.nsa3Oms7/pbuilderrc_RPwo --distribution unstable --hookdir /etc/pbuilder/first-build-hooks --debbuildopts -b --basetgz /var/cache/pbuilder/unstable-reproducible-base.tgz --buildresult /srv/reproducible-results/rbuild-debian/r-b-build.nsa3Oms7/b1 --logfile b1/build.log python-sse-starlette_2.2.1-1.dsc' - SUDO_GID='111' - SUDO_UID='106' - SUDO_USER='jenkins' - TERM='unknown' - TZ='/usr/share/zoneinfo/Etc/GMT+12' - USER='root' - _='/usr/bin/systemd-run' - http_proxy='http://213.165.73.152:3128' + PWD=/ + SHELL=/bin/bash + SHELLOPTS=braceexpand:errexit:hashall:interactive-comments:posix + SHLVL=3 + SUDO_COMMAND='/usr/bin/timeout -k 24.1h 24h /usr/bin/ionice -c 3 /usr/bin/nice -n 11 /usr/bin/unshare --uts -- /usr/sbin/pbuilder --build --configfile /srv/reproducible-results/rbuild-debian/r-b-build.nsa3Oms7/pbuilderrc_MzNH --distribution unstable --hookdir /etc/pbuilder/rebuild-hooks --debbuildopts -b --basetgz /var/cache/pbuilder/unstable-reproducible-base.tgz --buildresult /srv/reproducible-results/rbuild-debian/r-b-build.nsa3Oms7/b2 --logfile b2/build.log python-sse-starlette_2.2.1-1.dsc' + SUDO_GID=110 + SUDO_UID=105 + SUDO_USER=jenkins + TERM=unknown + TZ=/usr/share/zoneinfo/Etc/GMT-14 + UID=0 + USER=root + _='I: set' + http_proxy=http://46.16.76.132:3128 I: uname -a - Linux ionos15-amd64 6.12.9+bpo-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.12.9-1~bpo12+1 (2025-01-19) x86_64 GNU/Linux + Linux i-capture-the-hostname 6.1.0-31-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.128-1 (2025-02-07) x86_64 GNU/Linux I: ls -l /bin - lrwxrwxrwx 1 root root 7 Nov 22 2024 /bin -> usr/bin -I: user script /srv/workspace/pbuilder/957030/tmp/hooks/D02_print_environment finished + lrwxrwxrwx 1 root root 7 Nov 22 14:40 /bin -> usr/bin +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/D02_print_environment finished -> Attempting to satisfy build-dependencies -> Creating pbuilder-satisfydepends-dummy package Package: pbuilder-satisfydepends-dummy @@ -240,7 +272,7 @@ Get: 109 http://deb.debian.org/debian unstable/main amd64 python3-urllib3 all 2.3.0-1 [114 kB] Get: 110 http://deb.debian.org/debian unstable/main amd64 python3-requests all 2.32.3+dfsg-4 [72.1 kB] Get: 111 http://deb.debian.org/debian unstable/main amd64 python3-starlette all 0.41.3-2 [51.2 kB] -Fetched 39.9 MB in 19s (2083 kB/s) +Fetched 39.9 MB in 1s (45.0 MB/s) Preconfiguring packages ... Selecting previously unselected package libpython3.13-minimal:amd64. (Reading database ... (Reading database ... 5% (Reading database ... 10% (Reading database ... 15% (Reading database ... 20% (Reading database ... 25% (Reading database ... 30% (Reading database ... 35% (Reading database ... 40% (Reading database ... 45% (Reading database ... 50% (Reading database ... 55% (Reading database ... 60% (Reading database ... 65% (Reading database ... 70% (Reading database ... 75% (Reading database ... 80% (Reading database ... 85% (Reading database ... 90% (Reading database ... 95% (Reading database ... 100% (Reading database ... 19775 files and directories currently installed.) @@ -609,8 +641,8 @@ Setting up tzdata (2025a-2) ... Current default time zone: 'Etc/UTC' -Local time is now: Fri Mar 27 14:03:59 UTC 2026. -Universal Time is now: Fri Mar 27 14:03:59 UTC 2026. +Local time is now: Sat Feb 22 07:42:43 UTC 2025. +Universal Time is now: Sat Feb 22 07:42:43 UTC 2025. Run 'dpkg-reconfigure tzdata' if you wish to change it. Setting up autotools-dev (20220109.1) ... @@ -720,7 +752,11 @@ Building tag database... -> Finished parsing the build-deps I: Building the package -I: Running cd /build/reproducible-path/python-sse-starlette-2.2.1/ && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" HOME="/nonexistent/first-build" dpkg-buildpackage -us -uc -b && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games" HOME="/nonexistent/first-build" dpkg-genchanges -S > ../python-sse-starlette_2.2.1-1_source.changes +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/A99_set_merged_usr starting +Not re-configuring usrmerge for unstable +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/A99_set_merged_usr finished +hostname: Name or service not known +I: Running cd /build/reproducible-path/python-sse-starlette-2.2.1/ && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" HOME="/nonexistent/second-build" dpkg-buildpackage -us -uc -b && env PATH="/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/i/capture/the/path" HOME="/nonexistent/second-build" dpkg-genchanges -S > ../python-sse-starlette_2.2.1-1_source.changes dpkg-buildpackage: info: source package python-sse-starlette dpkg-buildpackage: info: source version 2.2.1-1 dpkg-buildpackage: info: source distribution unstable @@ -770,15 +806,15 @@ running install_lib creating build/bdist.linux-x86_64/wheel creating build/bdist.linux-x86_64/wheel/sse_starlette -copying build/lib/sse_starlette/py.typed -> build/bdist.linux-x86_64/wheel/./sse_starlette copying build/lib/sse_starlette/event.py -> build/bdist.linux-x86_64/wheel/./sse_starlette copying build/lib/sse_starlette/__init__.py -> build/bdist.linux-x86_64/wheel/./sse_starlette +copying build/lib/sse_starlette/py.typed -> build/bdist.linux-x86_64/wheel/./sse_starlette copying build/lib/sse_starlette/sse.py -> build/bdist.linux-x86_64/wheel/./sse_starlette running install_egg_info Copying sse_starlette.egg-info to build/bdist.linux-x86_64/wheel/./sse_starlette-2.2.1.egg-info running install_scripts creating build/bdist.linux-x86_64/wheel/sse_starlette-2.2.1.dist-info/WHEEL -creating '/build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.12_sse_starlette/.tmp-mfyn_i91/sse_starlette-2.2.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it +creating '/build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.12_sse_starlette/.tmp-is2fk1j9/sse_starlette-2.2.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it adding 'sse_starlette/__init__.py' adding 'sse_starlette/event.py' adding 'sse_starlette/py.typed' @@ -812,15 +848,15 @@ running install_lib creating build/bdist.linux-x86_64/wheel creating build/bdist.linux-x86_64/wheel/sse_starlette -copying build/lib/sse_starlette/py.typed -> build/bdist.linux-x86_64/wheel/./sse_starlette copying build/lib/sse_starlette/event.py -> build/bdist.linux-x86_64/wheel/./sse_starlette copying build/lib/sse_starlette/__init__.py -> build/bdist.linux-x86_64/wheel/./sse_starlette +copying build/lib/sse_starlette/py.typed -> build/bdist.linux-x86_64/wheel/./sse_starlette copying build/lib/sse_starlette/sse.py -> build/bdist.linux-x86_64/wheel/./sse_starlette running install_egg_info Copying sse_starlette.egg-info to build/bdist.linux-x86_64/wheel/./sse_starlette-2.2.1.egg-info running install_scripts creating build/bdist.linux-x86_64/wheel/sse_starlette-2.2.1.dist-info/WHEEL -creating '/build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.13_sse_starlette/.tmp-siymh9gq/sse_starlette-2.2.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it +creating '/build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.13_sse_starlette/.tmp-bo6j6f4p/sse_starlette-2.2.1-py3-none-any.whl' and adding 'build/bdist.linux-x86_64/wheel' to it adding 'sse_starlette/__init__.py' adding 'sse_starlette/event.py' adding 'sse_starlette/py.typed' @@ -844,20 +880,114 @@ platform linux -- Python 3.12.9, pytest-8.3.4, pluggy-1.5.0 rootdir: /build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.12_sse_starlette/build configfile: pyproject.toml -plugins: cov-5.0.0, anyio-4.8.0, typeguard-4.4.1, asyncio-0.25.1 +plugins: asyncio-0.25.1, cov-5.0.0, typeguard-4.4.1, anyio-4.8.0 asyncio: mode=Mode.AUTO, asyncio_default_fixture_loop_scope=None collected 44 items tests/test_event.py ....................... [ 52%] -tests/test_sse.py ..................... [100%] +tests/test_sse.py ..F.................. [100%] +=================================== FAILURES =================================== +_ TestEventSourceResponse.test_response_send_whenValidInput_thenGeneratesExpectedOutput[dict_with_event-\r\n-event: message\r\ndata: 1\r\n\r\n] _ + +self = +reset_appstatus_event = None +mock_generator = .numbers at 0x7fa2ed4ac180> +input_type = 'dict_with_event', separator = '\r\n' +expected_output = b'event: message\r\ndata: 1\r\n\r\n' + + @pytest.mark.parametrize( + "input_type,separator,expected_output", + [ + ("integer", "\r\n", b"data: 1\r\n\r\n"), + ("dict_simple", "\r\n", b"data: 1\r\n\r\n"), + ("dict_with_event", "\r\n", b"event: message\r\ndata: 1\r\n\r\n"), + ("dict_with_event", "\r", b"event: message\rdata: 1\r\r"), + ], + ) + async def test_response_send_whenValidInput_thenGeneratesExpectedOutput( + self, + reset_appstatus_event, + mock_generator, + input_type, + separator, + expected_output, + ): + # Arrange + async def app(scope, receive, send): + async def format_output(value): + if input_type == "integer": + return value + elif input_type == "dict_simple": + return dict(data=value) + else: + return dict(data=value, event="message") + + async def generate(): + generator = mock_generator(1, 5) + async for value in generator: + yield await format_output(value) + + response = EventSourceResponse(generate(), ping=0.2, sep=separator) + await response(scope, receive, send) + + # Act + client = TestClient(app) + response = client.get("/") + + # Assert + assert expected_output in response.content +> assert response.content.decode().count("ping") == 2 +E AssertionError: assert 3 == 2 +E + where 3 = ('ping') +E + where = 'event: message\r\ndata: 1\r\n\r\n: ping - 2025-02-22 07:44:07.287305+00:00\r\n\r\nevent: message\r\ndata: 2\r\n\r\n: ...r\nevent: message\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:07.747025+00:00\r\n\r\nevent: message\r\ndata: 5\r\n\r\n'.count +E + where 'event: message\r\ndata: 1\r\n\r\n: ping - 2025-02-22 07:44:07.287305+00:00\r\n\r\nevent: message\r\ndata: 2\r\n\r\n: ...r\nevent: message\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:07.747025+00:00\r\n\r\nevent: message\r\ndata: 5\r\n\r\n' = () +E + where = b'event: message\r\ndata: 1\r\n\r\n: ping - 2025-02-22 07:44:07.287305+00:00\r\n\r\nevent: message\r\ndata: 2\r\n\r\n:...r\nevent: message\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:07.747025+00:00\r\n\r\nevent: message\r\ndata: 5\r\n\r\n'.decode +E + where b'event: message\r\ndata: 1\r\n\r\n: ping - 2025-02-22 07:44:07.287305+00:00\r\n\r\nevent: message\r\ndata: 2\r\n\r\n:...r\nevent: message\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:07.747025+00:00\r\n\r\nevent: message\r\ndata: 5\r\n\r\n' = .content + +tests/test_sse.py:82: AssertionError +---------------------------- Captured stderr setup ----------------------------- +2025-02-22 21:44:07 DEBUG asyncio __init__:64 Using selector: EpollSelector +------------------------------ Captured log setup ------------------------------ +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +----------------------------- Captured stderr call ----------------------------- +2025-02-22 21:44:07 DEBUG asyncio __init__:64 Using selector: EpollSelector +2025-02-22 21:44:07 DEBUG sse_starlette.sse _stream_response:156 chunk: b'event: message\r\ndata: 1\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:07.287305+00:00\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _stream_response:156 chunk: b'event: message\r\ndata: 2\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:07.488239+00:00\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _stream_response:156 chunk: b'event: message\r\ndata: 3\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _stream_response:156 chunk: b'event: message\r\ndata: 4\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:07.747025+00:00\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _stream_response:156 chunk: b'event: message\r\ndata: 5\r\n\r\n' +2025-02-22 21:44:07 DEBUG sse_starlette.sse _listen_for_disconnect:177 Got event: http.disconnect. Stop streaming. +2025-02-22 21:44:07 INFO httpx _send_single_request:1038 HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +------------------------------ Captured log call ------------------------------- +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +DEBUG sse_starlette.sse:sse.py:156 chunk: b'event: message\r\ndata: 1\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:07.287305+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'event: message\r\ndata: 2\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:07.488239+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'event: message\r\ndata: 3\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'event: message\r\ndata: 4\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:07.747025+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'event: message\r\ndata: 5\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:177 Got event: http.disconnect. Stop streaming. +INFO httpx:_client.py:1038 HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +--------------------------- Captured stderr teardown --------------------------- +2025-02-22 21:44:07 DEBUG asyncio __init__:64 Using selector: EpollSelector +---------------------------- Captured log teardown ----------------------------- +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector =============================== warnings summary =============================== tests/test_sse.py::TestEventSourceResponse::test_disconnect_whenClientDisconnects_thenHandlesGracefully /usr/lib/python3/dist-packages/starlette/routing.py:599: DeprecationWarning: The on_startup and on_shutdown parameters are deprecated, and they will be removed on version 1.0. Use the lifespan parameter instead. See more about it on https://www.starlette.io/lifespan/. warnings.warn( -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html -======================== 44 passed, 1 warning in 7.77s ========================= +=========================== short test summary info ============================ +FAILED tests/test_sse.py::TestEventSourceResponse::test_response_send_whenValidInput_thenGeneratesExpectedOutput[dict_with_event-\r\n-event: message\r\ndata: 1\r\n\r\n] +=================== 1 failed, 43 passed, 1 warning in 9.45s ==================== +E: pybuild pybuild:389: test: plugin pyproject failed with: exit code=1: cd /build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.12_sse_starlette/build; python3.12 -m pytest --ignore tests/experimentation/test_multiple_consumers_asyncio.py --ignore tests/experimentation/test_multiple_consumers_threads.py --ignore tests/integration/test_multiple_consumers.py I: pybuild base:311: cd /build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.13_sse_starlette/build; python3.13 -m pytest --ignore tests/experimentation/test_multiple_consumers_asyncio.py --ignore tests/experimentation/test_multiple_consumers_threads.py --ignore tests/integration/test_multiple_consumers.py /usr/lib/python3/dist-packages/pytest_asyncio/plugin.py:207: PytestDeprecationWarning: The configuration option "asyncio_default_fixture_loop_scope" is unset. The event loop scope for asynchronous fixtures will default to the fixture caching scope. Future versions of pytest-asyncio will default the loop scope for asynchronous fixtures to function scope. Set the default fixture loop scope explicitly in order to avoid unexpected behavior in the future. Valid fixture loop scopes are: "function", "class", "module", "package", "session" @@ -867,56 +997,223 @@ platform linux -- Python 3.13.2, pytest-8.3.4, pluggy-1.5.0 rootdir: /build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.13_sse_starlette/build configfile: pyproject.toml -plugins: cov-5.0.0, anyio-4.8.0, typeguard-4.4.1, asyncio-0.25.1 +plugins: asyncio-0.25.1, cov-5.0.0, typeguard-4.4.1, anyio-4.8.0 asyncio: mode=Mode.AUTO, asyncio_default_fixture_loop_scope=None collected 44 items tests/test_event.py ....................... [ 52%] -tests/test_sse.py ..................... [100%] +tests/test_sse.py FF................... [100%] + +=================================== FAILURES =================================== +_ TestEventSourceResponse.test_response_send_whenValidInput_thenGeneratesExpectedOutput[integer-\r\n-data: 1\r\n\r\n] _ +self = +reset_appstatus_event = None +mock_generator = .numbers at 0x7fd0bd2758a0> +input_type = 'integer', separator = '\r\n', expected_output = b'data: 1\r\n\r\n' + + @pytest.mark.parametrize( + "input_type,separator,expected_output", + [ + ("integer", "\r\n", b"data: 1\r\n\r\n"), + ("dict_simple", "\r\n", b"data: 1\r\n\r\n"), + ("dict_with_event", "\r\n", b"event: message\r\ndata: 1\r\n\r\n"), + ("dict_with_event", "\r", b"event: message\rdata: 1\r\r"), + ], + ) + async def test_response_send_whenValidInput_thenGeneratesExpectedOutput( + self, + reset_appstatus_event, + mock_generator, + input_type, + separator, + expected_output, + ): + # Arrange + async def app(scope, receive, send): + async def format_output(value): + if input_type == "integer": + return value + elif input_type == "dict_simple": + return dict(data=value) + else: + return dict(data=value, event="message") + + async def generate(): + generator = mock_generator(1, 5) + async for value in generator: + yield await format_output(value) + + response = EventSourceResponse(generate(), ping=0.2, sep=separator) + await response(scope, receive, send) + + # Act + client = TestClient(app) + response = client.get("/") + + # Assert + assert expected_output in response.content +> assert response.content.decode().count("ping") == 2 +E AssertionError: assert 3 == 2 +E + where 3 = ('ping') +E + where = 'data: 1\r\n\r\n: ping - 2025-02-22 07:44:18.923768+00:00\r\n\r\ndata: 2\r\n\r\ndata: 3\r\n\r\n: ping - 2025-02-22 07:44:19.265358+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:19.466357+00:00\r\n\r\ndata: 5\r\n\r\n'.count +E + where 'data: 1\r\n\r\n: ping - 2025-02-22 07:44:18.923768+00:00\r\n\r\ndata: 2\r\n\r\ndata: 3\r\n\r\n: ping - 2025-02-22 07:44:19.265358+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:19.466357+00:00\r\n\r\ndata: 5\r\n\r\n' = () +E + where = b'data: 1\r\n\r\n: ping - 2025-02-22 07:44:18.923768+00:00\r\n\r\ndata: 2\r\n\r\ndata: 3\r\n\r\n: ping - 2025-02-22 07:44:19.265358+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:19.466357+00:00\r\n\r\ndata: 5\r\n\r\n'.decode +E + where b'data: 1\r\n\r\n: ping - 2025-02-22 07:44:18.923768+00:00\r\n\r\ndata: 2\r\n\r\ndata: 3\r\n\r\n: ping - 2025-02-22 07:44:19.265358+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:19.466357+00:00\r\n\r\ndata: 5\r\n\r\n' = .content + +tests/test_sse.py:82: AssertionError +---------------------------- Captured stderr setup ----------------------------- +2025-02-22 21:44:18 DEBUG asyncio __init__:64 Using selector: EpollSelector +2025-02-22 21:44:18 DEBUG asyncio __init__:64 Using selector: EpollSelector +------------------------------ Captured log setup ------------------------------ +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +----------------------------- Captured stderr call ----------------------------- +2025-02-22 21:44:18 DEBUG asyncio __init__:64 Using selector: EpollSelector +2025-02-22 21:44:18 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 1\r\n\r\n' +2025-02-22 21:44:18 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:18.923768+00:00\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 2\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 3\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:19.265358+00:00\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 4\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:19.466357+00:00\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 5\r\n\r\n' +2025-02-22 21:44:19 DEBUG sse_starlette.sse _listen_for_disconnect:177 Got event: http.disconnect. Stop streaming. +2025-02-22 21:44:19 INFO httpx _send_single_request:1038 HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +------------------------------ Captured log call ------------------------------- +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 1\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:18.923768+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 2\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 3\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:19.265358+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 4\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:19.466357+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 5\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:177 Got event: http.disconnect. Stop streaming. +INFO httpx:_client.py:1038 HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +--------------------------- Captured stderr teardown --------------------------- +2025-02-22 21:44:19 DEBUG asyncio __init__:64 Using selector: EpollSelector +---------------------------- Captured log teardown ----------------------------- +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +_ TestEventSourceResponse.test_response_send_whenValidInput_thenGeneratesExpectedOutput[dict_simple-\r\n-data: 1\r\n\r\n] _ + +self = +reset_appstatus_event = None +mock_generator = .numbers at 0x7fd0bd2767a0> +input_type = 'dict_simple', separator = '\r\n' +expected_output = b'data: 1\r\n\r\n' + + @pytest.mark.parametrize( + "input_type,separator,expected_output", + [ + ("integer", "\r\n", b"data: 1\r\n\r\n"), + ("dict_simple", "\r\n", b"data: 1\r\n\r\n"), + ("dict_with_event", "\r\n", b"event: message\r\ndata: 1\r\n\r\n"), + ("dict_with_event", "\r", b"event: message\rdata: 1\r\r"), + ], + ) + async def test_response_send_whenValidInput_thenGeneratesExpectedOutput( + self, + reset_appstatus_event, + mock_generator, + input_type, + separator, + expected_output, + ): + # Arrange + async def app(scope, receive, send): + async def format_output(value): + if input_type == "integer": + return value + elif input_type == "dict_simple": + return dict(data=value) + else: + return dict(data=value, event="message") + + async def generate(): + generator = mock_generator(1, 5) + async for value in generator: + yield await format_output(value) + + response = EventSourceResponse(generate(), ping=0.2, sep=separator) + await response(scope, receive, send) + + # Act + client = TestClient(app) + response = client.get("/") + + # Assert + assert expected_output in response.content +> assert response.content.decode().count("ping") == 2 +E AssertionError: assert 4 == 2 +E + where 4 = ('ping') +E + where = 'data: 1\r\n\r\n: ping - 2025-02-22 07:44:20.136712+00:00\r\n\r\ndata: 2\r\n\r\n: ping - 2025-02-22 07:44:20.396273+00...025-02-22 07:44:20.597271+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:20.798491+00:00\r\n\r\ndata: 5\r\n\r\n'.count +E + where 'data: 1\r\n\r\n: ping - 2025-02-22 07:44:20.136712+00:00\r\n\r\ndata: 2\r\n\r\n: ping - 2025-02-22 07:44:20.396273+00...025-02-22 07:44:20.597271+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:20.798491+00:00\r\n\r\ndata: 5\r\n\r\n' = () +E + where = b'data: 1\r\n\r\n: ping - 2025-02-22 07:44:20.136712+00:00\r\n\r\ndata: 2\r\n\r\n: ping - 2025-02-22 07:44:20.396273+0...025-02-22 07:44:20.597271+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:20.798491+00:00\r\n\r\ndata: 5\r\n\r\n'.decode +E + where b'data: 1\r\n\r\n: ping - 2025-02-22 07:44:20.136712+00:00\r\n\r\ndata: 2\r\n\r\n: ping - 2025-02-22 07:44:20.396273+0...025-02-22 07:44:20.597271+00:00\r\n\r\ndata: 4\r\n\r\n: ping - 2025-02-22 07:44:20.798491+00:00\r\n\r\ndata: 5\r\n\r\n' = .content + +tests/test_sse.py:82: AssertionError +---------------------------- Captured stderr setup ----------------------------- +2025-02-22 21:44:19 DEBUG asyncio __init__:64 Using selector: EpollSelector +------------------------------ Captured log setup ------------------------------ +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +----------------------------- Captured stderr call ----------------------------- +2025-02-22 21:44:19 DEBUG asyncio __init__:64 Using selector: EpollSelector +2025-02-22 21:44:19 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 1\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:20.136712+00:00\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 2\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:20.396273+00:00\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 3\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:20.597271+00:00\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 4\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _ping:211 ping: b': ping - 2025-02-22 07:44:20.798491+00:00\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _stream_response:156 chunk: b'data: 5\r\n\r\n' +2025-02-22 21:44:20 DEBUG sse_starlette.sse _listen_for_disconnect:177 Got event: http.disconnect. Stop streaming. +2025-02-22 21:44:20 INFO httpx _send_single_request:1038 HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +------------------------------ Captured log call ------------------------------- +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 1\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:20.136712+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 2\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:20.396273+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 3\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:20.597271+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 4\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:211 ping: b': ping - 2025-02-22 07:44:20.798491+00:00\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:156 chunk: b'data: 5\r\n\r\n' +DEBUG sse_starlette.sse:sse.py:177 Got event: http.disconnect. Stop streaming. +INFO httpx:_client.py:1038 HTTP Request: GET http://testserver/ "HTTP/1.1 200 OK" +--------------------------- Captured stderr teardown --------------------------- +2025-02-22 21:44:20 DEBUG asyncio __init__:64 Using selector: EpollSelector +---------------------------- Captured log teardown ----------------------------- +DEBUG asyncio:selector_events.py:64 Using selector: EpollSelector =============================== warnings summary =============================== tests/test_sse.py::TestEventSourceResponse::test_disconnect_whenClientDisconnects_thenHandlesGracefully /usr/lib/python3/dist-packages/starlette/routing.py:599: DeprecationWarning: The on_startup and on_shutdown parameters are deprecated, and they will be removed on version 1.0. Use the lifespan parameter instead. See more about it on https://www.starlette.io/lifespan/. warnings.warn( -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html -======================== 44 passed, 1 warning in 7.67s ========================= - create-stamp debian/debhelper-build-stamp - dh_testroot -O--buildsystem=pybuild - dh_prep -O--buildsystem=pybuild - dh_auto_install --destdir=debian/python3-sse-starlette/ -O--buildsystem=pybuild -I: pybuild plugin_pyproject:178: Copying package built for python3.12 to destdir -I: pybuild plugin_pyproject:178: Copying package built for python3.13 to destdir - dh_installdocs -O--buildsystem=pybuild - dh_installchangelogs -O--buildsystem=pybuild - dh_installexamples -O--buildsystem=pybuild - dh_python3 -O--buildsystem=pybuild - dh_installsystemduser -O--buildsystem=pybuild - dh_perl -O--buildsystem=pybuild - dh_link -O--buildsystem=pybuild - dh_strip_nondeterminism -O--buildsystem=pybuild - dh_compress -O--buildsystem=pybuild - dh_fixperms -O--buildsystem=pybuild - dh_missing -O--buildsystem=pybuild - dh_installdeb -O--buildsystem=pybuild - dh_gencontrol -O--buildsystem=pybuild - dh_md5sums -O--buildsystem=pybuild - dh_builddeb -O--buildsystem=pybuild -dpkg-deb: building package 'python3-sse-starlette' in '../python3-sse-starlette_2.2.1-1_all.deb'. - dpkg-genbuildinfo --build=binary -O../python-sse-starlette_2.2.1-1_amd64.buildinfo - dpkg-genchanges --build=binary -O../python-sse-starlette_2.2.1-1_amd64.changes -dpkg-genchanges: info: binary-only upload (no source code included) - dpkg-source --after-build . -dpkg-source: info: using options from python-sse-starlette-2.2.1/debian/source/options: --extend-diff-ignore=^[^/]*[.]egg-info/ -dpkg-buildpackage: info: binary-only upload (no source included) -dpkg-genchanges: info: including full source code in upload +=========================== short test summary info ============================ +FAILED tests/test_sse.py::TestEventSourceResponse::test_response_send_whenValidInput_thenGeneratesExpectedOutput[integer-\r\n-data: 1\r\n\r\n] +FAILED tests/test_sse.py::TestEventSourceResponse::test_response_send_whenValidInput_thenGeneratesExpectedOutput[dict_simple-\r\n-data: 1\r\n\r\n] +=================== 2 failed, 42 passed, 1 warning in 9.59s ==================== +E: pybuild pybuild:389: test: plugin pyproject failed with: exit code=1: cd /build/reproducible-path/python-sse-starlette-2.2.1/.pybuild/cpython3_3.13_sse_starlette/build; python3.13 -m pytest --ignore tests/experimentation/test_multiple_consumers_asyncio.py --ignore tests/experimentation/test_multiple_consumers_threads.py --ignore tests/integration/test_multiple_consumers.py +dh_auto_test: error: pybuild --test --test-pytest -i python{version} -p "3.12 3.13" returned exit code 13 +make: *** [debian/rules:14: binary] Error 25 +dpkg-buildpackage: error: debian/rules binary subprocess returned exit status 2 I: copying local configuration +E: Failed autobuilding of package +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/C01_cleanup starting +debug output: disk usage on i-capture-the-hostname at Sat Feb 22 07:44:28 UTC 2025 +Filesystem Size Used Avail Use% Mounted on +tmpfs 40G 0 40G 0% /dev/shm + +I: user script /srv/workspace/pbuilder/1539955/tmp/hooks/C01_cleanup finished I: unmounting dev/ptmx filesystem I: unmounting dev/pts filesystem I: unmounting dev/shm filesystem I: unmounting proc filesystem I: unmounting sys filesystem I: cleaning the build env -I: removing directory /srv/workspace/pbuilder/957030 and its subdirectories -I: Current time: Fri Mar 27 02:04:51 -12 2026 -I: pbuilder-time-stamp: 1774620291 +I: removing directory /srv/workspace/pbuilder/1539955 and its subdirectories