Skip to content

Commit c77f2ad

Browse files
authored
python: Fix a bug where aborting early from a stream would close a connection. (#545)
1 parent aeeb497 commit c77f2ad

File tree

5 files changed

+54
-3
lines changed

5 files changed

+54
-3
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
8.7.0
1+
8.7.1

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
[tool.poetry]
55
name = "dazl"
6-
version = "8.7.0"
6+
version = "8.7.1"
77
description = "high-level Ledger API client for Daml ledgers"
88
license = "Apache-2.0"
99
authors = ["Davin K. Tanabe <[email protected]>"]

python/dazl/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,4 @@
5757
pass
5858

5959

60-
__version__ = "8.7.0"
60+
__version__ = "8.7.1"

python/dazl/ledger/errors.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,19 @@ def __enter__(self):
8888
return self
8989

9090
def __exit__(self, exc_type, exc_val, exc_tb):
91+
if isinstance(exc_val, GeneratorExit):
92+
return None
93+
9194
if exc_val is not None and self.conn.is_closed:
9295
raise ConnectionClosedError() from exc_val
9396

9497
async def __aenter__(self):
9598
return self
9699

97100
async def __aexit__(self, exc_type, exc_val, exc_tb):
101+
if isinstance(exc_val, GeneratorExit):
102+
return None
103+
98104
if exc_val is not None and self.conn.is_closed:
99105
raise ConnectionClosedError() from exc_val
100106

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright (c) 2017-2025 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
from __future__ import annotations
5+
6+
import asyncio
7+
from datetime import timedelta
8+
import random
9+
from typing import Any
10+
11+
from dazl import Party, connect
12+
from dazl.ledger.aio import Connection
13+
from dazl.testing import SandboxLauncher, sandbox
14+
import pytest
15+
16+
from .dars import Simple
17+
18+
19+
@pytest.mark.asyncio
20+
async def test_early_stream_abort(sandbox: SandboxLauncher) -> None:
21+
async with connect(url=sandbox.url) as conn:
22+
await conn.upload_package(Simple.read_bytes())
23+
alice = await conn.allocate_party(identifier_hint="Alice")
24+
for i in range(100):
25+
await conn.create(
26+
"Simple:OperatorNotification",
27+
{
28+
"operator": alice.party,
29+
"theObservers": [],
30+
"text": f"{random.random()}",
31+
},
32+
act_as=alice.party,
33+
)
34+
35+
for i in range(10):
36+
payload = await find_one(conn, alice.party, str(i / 10))
37+
38+
39+
async def find_one(conn: Connection, party: Party, prefix: str) -> Any:
40+
async with conn.stream("Simple:OperatorNotification", read_as=party) as stream:
41+
async for ev in stream.creates():
42+
if ev.payload["text"].startswith(prefix):
43+
return ev.payload
44+
45+
return None

0 commit comments

Comments
 (0)