Whole file

patrick-kidger/tinyio

The author described this change as Yielding already-started (but not yet completed, and not yet seen by the loop) generators will now correctly raise an error.. It counts as a record because the checks below fail on the code as it stood at e43ae6123 and pass on 199c5a01c, with nothing else changed between the two runs.

Fix saved2026-03-14
Sharing licenceApache-2.0 · LICENSE
Change size+6 6

What the code was meant to do, written into the code itself as a save note

Yielding already-started (but not yet completed, and not yet seen by the loop) generators will now correctly raise an error.

The change

228228 for out_i in out:
229229 if isinstance(out_i, Generator):
230230 if out_i not in self._results.keys() and out_i not in waiting_on.keys():
231- if inspect.getgeneratorstate(out_i) == inspect.GEN_CLOSED:
232- todo.coro.throw(_already_finished(out_i))
231+ if inspect.getgeneratorstate(out_i) != inspect.GEN_CREATED:
232+ todo.coro.throw(_already_started(out_i))
233233 queue.appendleft(_Todo(out_i, None))
234234 waiting_on[out_i] = []
235235 else:
245245 elif out_i in waiting_on.keys():
246246 waiting_on[out_i].append(waiting_for)
247247 else:
248- if inspect.getgeneratorstate(out_i) == inspect.GEN_CLOSED:
249- todo.coro.throw(_already_finished(out_i))
248+ if inspect.getgeneratorstate(out_i) != inspect.GEN_CREATED:
249+ todo.coro.throw(_already_started(out_i))
250250 queue.appendleft(_Todo(out_i, None))
251251 waiting_on[out_i] = [waiting_for]
252252 elif isinstance(out_i, _Wait):
595595 return RuntimeError(msg)
596596
597597
598-def _already_finished(out):
598+def _already_started(out):
599599 return RuntimeError(
600- f"The coroutine `{out}` has already finished. However it has not been seen by the `tinyio` loop before and as "
600+ f"The coroutine `{out}` has already started. However it has not been seen by the `tinyio` loop before and as "
601601 "such does not have any result associated with it."
602602 )
603603

The check that tells the two apart

failpass·tests/test_core.py::test_yield_finished_coroutine[bare]
failpass·tests/test_core.py::test_yield_finished_coroutine[list]
failpass·tests/test_core.py::test_yield_finished_coroutine[set]
failpass·tests/test_core.py::test_yield_started_generator[bare]
failpass·tests/test_core.py::test_yield_started_generator[list]
failpass·tests/test_core.py::test_yield_started_generator[set]

Check file tests/test_core.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.

Origin and history

The code before ite43ae61239c188dc7063c38b7131e21be6dd1d21
Broken version dated2026-03-14
Moduletinyio._core
Units changedLoop
Fingerprint196539643abedf5d
Checked2026-08-18 by goldset/0.1

Every field above is generated by our program. None of it is written by hand.