First of all, I'm aware it is developers' responsibility to make sure your define your method as a coroutine when implementing child class
class MyBase(ABC):
@abstractclassmethod
def the_coroutine(self):
"""
I want this to be a coroutine
"""
class ImplBaseA(MyBase):
async def the_coroutine(self):
return "awaited"
class ImplBaseB(MyBase):
def the_coroutine(self):
# some condition that happens quite often
if True:
raise ValueError("From the first glance I was even awaited")
return "not the coroutine"
But how to prevent this issue in the code from occurring?
await a.the_coroutine()
# When inspecting the code it seems like it does the right thing
await b.the_coroutine()
# and when raising exception it really does
Should I use mypy or some similar tool? What's the pythonic way of making sure implementation is coroutine only (regular function only)?
You can augment the type of check done with an
ABCbase with an__init_subclass__method that would verify that any overriden methods have their "sinch/asynchness" maintained.That would be something along:
Of course, this will imply some artificial restriction as in overriden methods can't be synch functions returning awaitables.
Detecting this with static type checking and tools like MyPy would also work - I think the most straightforward way would be to create a
typing.Protocolspelling out the interface you create now with the abstract base class. (on the other hand, you can use only the static checking mechanism and not need the abstract base any more for other things as well).