Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f68b1d4

Browse files
authored
Merge branch 'master' into codependentcodr/ch255/add-dev-to-profile-link
2 parents cf3d49a + 7905932 commit f68b1d4

File tree

3 files changed

+95
-3
lines changed

3 files changed

+95
-3
lines changed

content/ptotd-asyncio-learnings.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Date: 2018-08-05 10:00
33
Modified: 2018-08-05 10:30
44
Category: Posts
55
tags: asyncio,python,ptotd
6-
cover: static/imgs/default_page_imagev2.jpg
6+
cover: static/imgs/python-logo-master-v3-TM.png
77
summary: Learning asyncio
88

99
Recently I've been digging into Python's `asyncio` library which was introduced

content/ptotd-asyncio-round2.md

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
Title: Asyncio part 2 - Now More Abstract
2+
Date: 2018-08-08 11:56
3+
Modified: 2018-08-08 11:56
4+
Category: Posts
5+
tags: python,ptotd,asyncio,coroutine,abstract,abc
6+
cover: static/imgs/python-logo-master-v3-TM.png
7+
summary: What happens when you mix coroutines with Abstract Base Classes?
8+
9+
Continuing on with my asyncio learnings. Had the opportunity to look at a wrinkle I haven't seen discussed
10+
much -- using coroutines with [Abstract Base Classes](https://docs.python.org/3/library/abc.html).
11+
12+
First question: can coroutines be abstract? Yes. Yes they can:
13+
14+
```python
15+
from abc import ABC, abstractmethod
16+
17+
import asyncio
18+
19+
20+
class AbstractBase(ABC):
21+
@abstractmethod
22+
async def meth1(self):
23+
pass
24+
25+
26+
class Concrete(AbstractBase):
27+
async def meth1(self):
28+
print("in concrete")
29+
30+
if __name__ == "__main__":
31+
loop = asyncio.get_event_loop()
32+
loop.run_until_complete(Concrete().meth1()) # prints "in concrete"
33+
```
34+
35+
Nothing particularly surprising there.
36+
37+
Next question: is an abstract class still uninstantiable? Yes. Yes it is:
38+
39+
```python
40+
>>> AbstractBase()
41+
Traceback (most recent call last):
42+
File "<stdin>", line 1, in <module>
43+
TypeError: Can't instantiate abstract class AbstractBase with abstract methods meth1
44+
```
45+
46+
Cool, so far so good.
47+
48+
Ok, next question: what happens if an implementing class doesn't denote an overriding
49+
method as a coroutine? Nothing:
50+
51+
```python
52+
class ConcreteButNotCoroutine(AbstractBase):
53+
def meth1(self):
54+
print("in concrete but not coroutine")
55+
```
56+
57+
However, this is where it gets a bit grey. `meth1()` on `ConcreteButNotCoroutine` is
58+
a method, not a coroutine, so it can't be passed to `run_until_complete()`:
59+
60+
```python
61+
>>> loop.run_until_complete(ConcreteButNotCoroutine().meth1())
62+
in concrete but not coroutine
63+
Traceback (most recent call last):
64+
File "<stdin>", line 1, in <module>
65+
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 547, in run_until_complete
66+
future = tasks.ensure_future(future, loop=self)
67+
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/tasks.py", line 588, in ensure_future
68+
raise TypeError('An asyncio.Future, a coroutine or an awaitable is '
69+
TypeError: An asyncio.Future, a coroutine or an awaitable is required
70+
```
71+
72+
This is kinda icky, now whomever is using a concrete implementation of `AbstractBase`
73+
has to know if the specific derived class marked `meth1()` as `async` or not. This
74+
seems to defeat much of the purpose of using an abstract base class in the first
75+
place as it's kind of a violation of the [Liskov Substitution Principle](https://en.wikipedia.org/wiki/Liskov_substitution_principle).
76+
The LSP is typically stated as (this is taken from the Wikipedia page):
77+
78+
> if S is a subtype of T, then objects of type T may be replaced with objects of
79+
> type S (i.e. an object of type T may be substituted with any object of a
80+
> subtype S) without altering any of the desirable properties of the program
81+
> (correctness, task performed, etc.)
82+
83+
That is, you should be able to use a `ConcreteButNotCoroutine` instance anywhere you
84+
can use a `Concrete` instance without having things go boom boom.
85+
86+
Python's long had a history of being a little lax with the typing (some would call
87+
that a feature, some would call it a shortcoming), but this feels a bit unfortunate.
88+
89+
I did some Googling and someone asked [this question on Stackoverflow](https://stackoverflow.com/questions/47555934/how-require-that-an-abstract-method-is-a-coroutine)
90+
which provides a workaround to check if an implementing class overrides an abstract coroutine
91+
with a coroutine, but still feels rather cumbersome. It also still results in a runtime error,
92+
just at object instantiation time instead of at method call time.

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
autopep8==1.3.5
2-
awscli==1.15.73
2+
awscli==1.15.76
33
bandit==1.4.0
44
black==18.6b4
5-
boto3==1.7.72
5+
boto3==1.7.75
66
flake8==3.5.0
77
Markdown==2.6.11
88
pelican==3.7.1

0 commit comments

Comments
 (0)