1 |
On 5/8/19 11:05 AM, Zac Medico wrote: |
2 |
> On 5/7/19 1:01 PM, Zac Medico wrote: |
3 |
>> On 5/7/19 7:55 AM, Alec Warner wrote: |
4 |
>> |
5 |
>>> Also curious why we are not implementing enter and exit so we can avoid |
6 |
>>> unbalanced pairs by using context managers. |
7 |
>>> |
8 |
>>> e.g. in match(), we could likely write: |
9 |
>>> |
10 |
>>> with self.dbapi.lock(): |
11 |
>>> # try to match |
12 |
>>> update_pkgindex = self._populate_local() |
13 |
>>> if update_pkgindex: |
14 |
>>> self._pkgindex_write(update_pkgindex) |
15 |
>>> |
16 |
>>> If the block raises an exception, __exit__ is still called, so we can |
17 |
>>> eliminate the finally: blocks and replace them with a careful __exit__ |
18 |
>>> implementation? |
19 |
>>> |
20 |
>>> -A |
21 |
>> |
22 |
>> Yeah, the reference counted lock class could have a method that returns |
23 |
>> a context manager which increments/decrements the lock count. The |
24 |
>> context manager can be implemented with the contextlib.contextmanager |
25 |
>> decorator like this: |
26 |
>> |
27 |
>> @contextlib.contextmanager |
28 |
>> def contextmanager(self): |
29 |
>> self.lock() |
30 |
>> try: |
31 |
>> yield self |
32 |
>> finally: |
33 |
>> self.unlock() |
34 |
>> |
35 |
> |
36 |
> Since we really don't want asynchronous code to block waiting for a |
37 |
> lock, we really should use a (python3.5+ only) asynchronous context manager: |
38 |
> |
39 |
> https://www.python.org/dev/peps/pep-0492/#asynchronous-context-managers-and-async-with |
40 |
> |
41 |
> Given that python2.7 is scheduled for retirement in 2020 |
42 |
> (https://pythonclock.org/), maybe it's time to drop support for |
43 |
> python3.4 and earlier. |
44 |
|
45 |
Adapting the sample code provided in PEP 492, we can do something like |
46 |
this for compatibility with older versions of python: |
47 |
|
48 |
from portage.util.futures.compat_coroutine |
49 |
|
50 |
@compat_coroutine.coroutine |
51 |
def async_with(mgr, async_func): |
52 |
aexit = type(mgr).__aexit__ |
53 |
aenter = type(mgr).__aenter__(mgr) |
54 |
|
55 |
aenter_result = (yield aenter) |
56 |
try: |
57 |
return_value = (yield async_func(aenter_result)) |
58 |
except: |
59 |
if not (yield aexit(mgr, *sys.exc_info()): |
60 |
raise |
61 |
else: |
62 |
yield aexit(mgr, None, None, None) |
63 |
|
64 |
compat_coroutine.coroutine_return(return_value) |
65 |
|
66 |
|
67 |
-- |
68 |
Thanks, |
69 |
Zac |