Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change in behavior of chain() between 3.10.5 and 3.10.6. #107

Closed
byllyfish opened this issue Apr 4, 2023 · 3 comments · Fixed by #108
Closed

Change in behavior of chain() between 3.10.5 and 3.10.6. #107

byllyfish opened this issue Apr 4, 2023 · 3 comments · Fixed by #108
Assignees

Comments

@byllyfish
Copy link

There is a subtle change in behavior introduced in the recent changes to chain(). Chain's iterator appears to be escaping from its "scope" when it is interrupted.

Here is an example program that produces different output. I'm using Python 3.11.2, but I don't think the Python version makes much difference.

import asyncio

import asyncstdlib as asl


async def gen1(*args):
    try:
        for i in args:
            yield i
    finally:
        print("FINALLY")


async def main():
    nums = asl.chain(gen1(1, 2, 3))
    nums = asl.takewhile(lambda x: x != 2, nums)

    async for n in nums:
        print(n)

    print("ALL DONE")


asyncio.run(main())

asyncstdlib 3.10.5 (correct output)

1
FINALLY
ALL DONE

asyncstdlib 3.10.6 (incorrect output)

1
ALL DONE
FINALLY
@byllyfish
Copy link
Author

Here's a construction of chain that seems to work better:

class _Chain1:
    def __call__(self, *iterables):
        async def impl():
            for iterable in iterables:
                async with asl.scoped_iter(iterable) as iterator:
                    async for item in iterator:
                        yield item

        return impl()

    # Add other async methods here...

chain = _Chain1()

@maxfischer2781 maxfischer2781 self-assigned this Apr 12, 2023
@maxfischer2781
Copy link
Owner

It looks like this is due to a missing aclose (which a class implementation needs explicitly). Thanks for the report.

maxfischer2781 added a commit that referenced this issue Apr 16, 2023
* added chain.aclose method for cleanup (closes #107)

* do not reconstruct chain implementation again and again

* use same implementation for chain and chain.from_iterable

* chain owns explicitly passed iterables
@byllyfish
Copy link
Author

The fix you committed passes all my tests. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants