Skip to content

Commit b6cbc8a

Browse files
committed
Handle legacy syntax for 'returning' a value
1 parent 276f6d8 commit b6cbc8a

File tree

2 files changed

+31
-1
lines changed

2 files changed

+31
-1
lines changed

src/firebase_functions/https_fn.py

+8-1
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,18 @@ class CallableRequest(_typing.Generic[_core.T]):
353353
_C2 = _typing.Callable[[CallableRequest[_typing.Any]], _typing.Any]
354354

355355
class _IterWithReturn:
356+
""" Utility class to capture return statements from a generator """
356357
def __init__(self, iterable):
357358
self.iterable = iterable
358359

359360
def __iter__(self):
360-
self.value = yield from self.iterable
361+
try:
362+
self.value = yield from self.iterable
363+
except RuntimeError as e:
364+
if isinstance(e.__cause__, StopIteration):
365+
self.value = e.__cause__.value
366+
else:
367+
raise
361368

362369
def _on_call_handler(func: _C2, request: Request,
363370
enforce_app_check: bool) -> Response:

tests/test_https_fn.py

+23
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ def yield_thrower(req: https_fn.CallableRequest[int]):
148148
"Can't read anymore"
149149
)
150150

151+
@https_fn.on_call()
152+
def legacy_yielder(req: https_fn.CallableRequest[int]):
153+
yield from range(req.data)
154+
# Prior to Python 3.3, this was the way "return" was handled
155+
# Python 3.5 made this messy however because it converts
156+
# raised StopIteration into a RuntimeError
157+
# pylint: disable=stop-iteration-return
158+
raise StopIteration("OK")
159+
151160
with app.test_request_context("/"):
152161
environ = EnvironBuilder(
153162
method="POST",
@@ -162,6 +171,20 @@ def yield_thrower(req: https_fn.CallableRequest[int]):
162171
self.assertEqual(response.status_code, 200)
163172
self.assertEqual(response.get_json(), { "result": "OK" })
164173

174+
with app.test_request_context("/"):
175+
environ = EnvironBuilder(
176+
method="POST",
177+
json={
178+
"data": 5
179+
}
180+
).get_environ()
181+
182+
request = Request(environ)
183+
response = legacy_yielder(request)
184+
185+
self.assertEqual(response.status_code, 200)
186+
self.assertEqual(response.get_json(), { "result": "OK" })
187+
165188
with app.test_request_context("/"):
166189
environ = EnvironBuilder(
167190
method="POST",

0 commit comments

Comments
 (0)