Skip to content

Implement async functions and generators (.NET)#2046

Open
BCSharp wants to merge 6 commits into
IronLanguages:mainfrom
BCSharp:net_async
Open

Implement async functions and generators (.NET)#2046
BCSharp wants to merge 6 commits into
IronLanguages:mainfrom
BCSharp:net_async

Conversation

@BCSharp
Copy link
Copy Markdown
Member

@BCSharp BCSharp commented May 28, 2026

This is an alternative implementation of PEP 492 from #2004 by @mikasoukhov (Python 3.5). It builds on top of async support in the DLR (IronLanguages/dlr#362), which is around native .NET async primitives: Task/Task<T>, IAsyncEnumerable<T>, IAsyncDisposable. As such, it fits better within a .NET ecosystem, e.g. IronPython engine embedded within a larger C# application. As a .NET async mechanism, it obeys the .NET scheduling and context following mechanisms. For Python behavioural compatibility, wrappers and bridges are provided.

It also implements PEP 525 (async generators), which are accepted in Python 3.6.

The previous async functionality in IronPython is still there, parallel to the new one, and which one is being used depends whether FEATURE_NET_ASYNC is being defined during compilation. If defined, the new functionality is being used, otherwise the previous functionality is being used. It is practical for testing and development, but perhaps some discrepancies will occur. I think in the end it is best to settle on just one mechanism, but I'd postpone this decision until the whole asyncio support is complete.

As it is now, FEATURE_NET_ASYNC is defined on .NET platforms, but undefined on .NET Framework 4.6.2.

Copy link
Copy Markdown
Contributor

@slozier slozier left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Apologies for the delay in reviewing this. Looks good to me!

I guess not having async generators in the other implementation is a bit of a blocker for a 3.6 release so this is good.



[LightThrowing]
public object athrow(object? type) => athrow(type, null, null);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just looking at future versions, it looks like the athrow argument is documented as value since 3.7 which seems reasonable to adopt? Also the other two overloads are deprecated in 3.12 (parhaps add a TODO comment?).



[LightThrowing]
public object @throw(object? type) => @throw(type, null, null);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as AsyncGenerator, the argument is value in 3.7 and the other overloads are deprecated in 3.12.


#if FEATURE_NET_ASYNC

[PythonType("coroutine")]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there's some shared code, perhaps move the class signature outside the feature branch instead or repeating it? Although don't feel strongly either way...

self.assertEqual(type(g).__name__, 'async_generator')


def test_asend(self):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess a bunch of these tests are not .NET specific. Maybe we could put them in a class that's not skipped? I guess our run_coro is .NET only, but that's easily substituted with asyncio.run (new in 3.7)... Ran into this while testing the tests against CPython.

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 this pull request may close these issues.

2 participants