ez-a-sync 0.22.13__py3-none-any.whl → 0.22.15__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of ez-a-sync might be problematic. Click here for more details.

Files changed (73) hide show
  1. a_sync/ENVIRONMENT_VARIABLES.py +4 -3
  2. a_sync/__init__.py +30 -12
  3. a_sync/_smart.py +132 -28
  4. a_sync/_typing.py +56 -12
  5. a_sync/a_sync/__init__.py +35 -10
  6. a_sync/a_sync/_descriptor.py +74 -26
  7. a_sync/a_sync/_flags.py +14 -6
  8. a_sync/a_sync/_helpers.py +8 -7
  9. a_sync/a_sync/_kwargs.py +3 -2
  10. a_sync/a_sync/_meta.py +120 -28
  11. a_sync/a_sync/abstract.py +102 -28
  12. a_sync/a_sync/base.py +34 -16
  13. a_sync/a_sync/config.py +47 -13
  14. a_sync/a_sync/decorator.py +239 -117
  15. a_sync/a_sync/function.py +416 -146
  16. a_sync/a_sync/method.py +197 -59
  17. a_sync/a_sync/modifiers/__init__.py +47 -5
  18. a_sync/a_sync/modifiers/cache/__init__.py +46 -17
  19. a_sync/a_sync/modifiers/cache/memory.py +86 -20
  20. a_sync/a_sync/modifiers/limiter.py +52 -22
  21. a_sync/a_sync/modifiers/manager.py +98 -16
  22. a_sync/a_sync/modifiers/semaphores.py +48 -15
  23. a_sync/a_sync/property.py +383 -82
  24. a_sync/a_sync/singleton.py +1 -0
  25. a_sync/aliases.py +0 -1
  26. a_sync/asyncio/__init__.py +4 -1
  27. a_sync/asyncio/as_completed.py +177 -49
  28. a_sync/asyncio/create_task.py +31 -17
  29. a_sync/asyncio/gather.py +72 -52
  30. a_sync/asyncio/utils.py +3 -3
  31. a_sync/exceptions.py +78 -23
  32. a_sync/executor.py +120 -71
  33. a_sync/future.py +575 -158
  34. a_sync/iter.py +110 -50
  35. a_sync/primitives/__init__.py +14 -2
  36. a_sync/primitives/_debug.py +13 -13
  37. a_sync/primitives/_loggable.py +5 -4
  38. a_sync/primitives/locks/__init__.py +5 -2
  39. a_sync/primitives/locks/counter.py +38 -36
  40. a_sync/primitives/locks/event.py +21 -7
  41. a_sync/primitives/locks/prio_semaphore.py +182 -62
  42. a_sync/primitives/locks/semaphore.py +78 -77
  43. a_sync/primitives/queue.py +560 -58
  44. a_sync/sphinx/__init__.py +0 -1
  45. a_sync/sphinx/ext.py +160 -50
  46. a_sync/task.py +262 -97
  47. a_sync/utils/__init__.py +12 -6
  48. a_sync/utils/iterators.py +127 -43
  49. {ez_a_sync-0.22.13.dist-info → ez_a_sync-0.22.15.dist-info}/METADATA +1 -1
  50. ez_a_sync-0.22.15.dist-info/RECORD +74 -0
  51. {ez_a_sync-0.22.13.dist-info → ez_a_sync-0.22.15.dist-info}/WHEEL +1 -1
  52. tests/conftest.py +1 -2
  53. tests/executor.py +112 -9
  54. tests/fixtures.py +61 -32
  55. tests/test_abstract.py +7 -4
  56. tests/test_as_completed.py +54 -21
  57. tests/test_base.py +66 -17
  58. tests/test_cache.py +31 -15
  59. tests/test_decorator.py +54 -28
  60. tests/test_executor.py +8 -13
  61. tests/test_future.py +45 -8
  62. tests/test_gather.py +8 -2
  63. tests/test_helpers.py +2 -0
  64. tests/test_iter.py +55 -13
  65. tests/test_limiter.py +5 -3
  66. tests/test_meta.py +23 -9
  67. tests/test_modified.py +4 -1
  68. tests/test_semaphore.py +15 -8
  69. tests/test_singleton.py +15 -10
  70. tests/test_task.py +126 -28
  71. ez_a_sync-0.22.13.dist-info/RECORD +0 -74
  72. {ez_a_sync-0.22.13.dist-info → ez_a_sync-0.22.15.dist-info}/LICENSE.txt +0 -0
  73. {ez_a_sync-0.22.13.dist-info → ez_a_sync-0.22.15.dist-info}/top_level.txt +0 -0
tests/fixtures.py CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import asyncio
3
2
  import time
4
3
  from threading import current_thread, main_thread
@@ -11,97 +10,124 @@ from a_sync import ASyncBase
11
10
  from a_sync.a_sync._meta import ASyncMeta, ASyncSingletonMeta
12
11
  from a_sync.a_sync.singleton import ASyncGenericSingleton
13
12
 
14
- increment = pytest.mark.parametrize('i', range(10))
13
+ increment = pytest.mark.parametrize("i", range(10))
14
+
15
+
16
+ class WrongThreadError(Exception): ...
15
17
 
16
- class WrongThreadError(Exception):
17
- ...
18
18
 
19
19
  class TestClass(ASyncBase):
20
20
  def __init__(self, v: int, sync: bool = False):
21
21
  self.v = v
22
22
  self.sync = sync
23
-
23
+
24
24
  async def test_fn(self) -> int:
25
25
  if self.sync == False and main_thread() != current_thread():
26
- raise WrongThreadError('This should be running on an event loop in the main thread.')
26
+ raise WrongThreadError(
27
+ "This should be running on an event loop in the main thread."
28
+ )
27
29
  elif self.sync == True and main_thread() != current_thread():
28
- raise WrongThreadError('This should be awaited in the main thread')
30
+ raise WrongThreadError("This should be awaited in the main thread")
29
31
  return self.v
30
-
32
+
31
33
  @a_sync.aka.property
32
34
  async def test_property(self) -> int:
33
35
  if self.sync == False and main_thread() != current_thread():
34
- raise WrongThreadError('This should be running on an event loop in the main thread.')
36
+ raise WrongThreadError(
37
+ "This should be running on an event loop in the main thread."
38
+ )
35
39
  elif self.sync == True and main_thread() != current_thread():
36
- raise WrongThreadError('This should be awaited in the main thread')
40
+ raise WrongThreadError("This should be awaited in the main thread")
37
41
  return self.v * 2
38
-
42
+
39
43
  @a_sync.alias.cached_property
40
44
  async def test_cached_property(self) -> int:
41
45
  if self.sync == False and main_thread() != current_thread():
42
- raise WrongThreadError('This should be running on an event loop in the main thread.')
46
+ raise WrongThreadError(
47
+ "This should be running on an event loop in the main thread."
48
+ )
43
49
  elif self.sync == True and main_thread() != current_thread():
44
- raise WrongThreadError('This should be awaited in the main thread')
50
+ raise WrongThreadError("This should be awaited in the main thread")
45
51
  await asyncio.sleep(2)
46
52
  return self.v * 3
47
53
 
54
+
48
55
  class TestSync(ASyncBase):
49
56
  main = main_thread()
57
+
50
58
  def __init__(self, v: int, sync: bool):
51
59
  self.v = v
52
60
  self.sync = sync
53
-
61
+
54
62
  def test_fn(self) -> int:
55
63
  # Sync bound methods are actually async functions that are run in an executor and awaited
56
64
  if self.sync == False and main_thread() == current_thread():
57
- raise WrongThreadError('This should be running in an executor, not the main thread.')
65
+ raise WrongThreadError(
66
+ "This should be running in an executor, not the main thread."
67
+ )
58
68
  elif self.sync == True and main_thread() != current_thread():
59
- raise WrongThreadError('This should be running synchronously in the main thread')
69
+ raise WrongThreadError(
70
+ "This should be running synchronously in the main thread"
71
+ )
60
72
  return self.v
61
-
73
+
62
74
  @a_sync.aka.property
63
75
  def test_property(self) -> int:
64
76
  if self.sync == False and main_thread() == current_thread():
65
- raise WrongThreadError('This should be running in an executor, not the main thread.')
77
+ raise WrongThreadError(
78
+ "This should be running in an executor, not the main thread."
79
+ )
66
80
  if self.sync == True and main_thread() == current_thread():
67
81
  # Sync properties are actually async functions that are run in an executor and awaited
68
- raise WrongThreadError('This should be running in an executor, not the main thread.')
82
+ raise WrongThreadError(
83
+ "This should be running in an executor, not the main thread."
84
+ )
69
85
  return self.v * 2
70
-
86
+
71
87
  @a_sync.alias.cached_property
72
88
  def test_cached_property(self) -> int:
73
89
  if self.sync == False and main_thread() == current_thread():
74
- raise WrongThreadError('This should be running in an executor, not the main thread.')
90
+ raise WrongThreadError(
91
+ "This should be running in an executor, not the main thread."
92
+ )
75
93
  if self.sync == True and main_thread() == current_thread():
76
94
  # Sync properties are actually async functions that are run in an executor and awaited
77
- raise WrongThreadError('This should be running in an executor, not the main thread.')
95
+ raise WrongThreadError(
96
+ "This should be running in an executor, not the main thread."
97
+ )
78
98
  time.sleep(2)
79
99
  return self.v * 3
80
100
 
101
+
81
102
  class TestLimiter(TestClass):
82
103
  limiter = 1
83
-
104
+
105
+
84
106
  class TestInheritor(TestClass):
85
107
  pass
86
108
 
109
+
87
110
  class TestMeta(TestClass, metaclass=ASyncMeta):
88
111
  pass
89
112
 
113
+
90
114
  class TestSingleton(ASyncGenericSingleton, TestClass):
91
115
  runs_per_minute = 100
92
116
  pass
93
117
 
118
+
94
119
  class TestSingletonMeta(TestClass, metaclass=ASyncSingletonMeta):
95
120
  semaphore = 1
96
121
  pass
97
122
 
123
+
98
124
  class TestSemaphore(ASyncBase):
99
- #semaphore=1 # NOTE: this is detected propely by undecorated test_fn but not the properties
100
-
125
+ # semaphore=1 # NOTE: this is detected propely by undecorated test_fn but not the properties
126
+
101
127
  def __init__(self, v: int, sync: bool):
102
128
  self.v = v
103
129
  self.sync = sync
104
-
130
+
105
131
  # spec on class and function both working
106
132
  @a_sync.a_sync(semaphore=1)
107
133
  async def test_fn(self) -> int:
@@ -109,11 +135,11 @@ class TestSemaphore(ASyncBase):
109
135
  return self.v
110
136
 
111
137
  # spec on class, function, property all working
112
- @a_sync.aka.property('async', semaphore=1)
138
+ @a_sync.aka.property("async", semaphore=1)
113
139
  async def test_property(self) -> int:
114
140
  await asyncio.sleep(1)
115
141
  return self.v * 2
116
-
142
+
117
143
  # spec on class, function, property all working
118
144
  @a_sync.alias.cached_property(semaphore=50)
119
145
  async def test_cached_property(self) -> int:
@@ -121,7 +147,7 @@ class TestSemaphore(ASyncBase):
121
147
  return self.v * 3
122
148
 
123
149
 
124
- def _test_kwargs(fn, default: Literal['sync','async',None]):
150
+ def _test_kwargs(fn, default: Literal["sync", "async", None]):
125
151
  # force async
126
152
  assert asyncio.get_event_loop().run_until_complete(fn(sync=False)) == 2
127
153
  assert asyncio.get_event_loop().run_until_complete(fn(asynchronous=True)) == 2
@@ -132,18 +158,21 @@ def _test_kwargs(fn, default: Literal['sync','async',None]):
132
158
  assert asyncio.get_event_loop().run_until_complete(fn(asynchronous=False)) == 2
133
159
  assert fn(sync=True) == 2
134
160
  assert fn(asynchronous=False) == 2
135
- if default == 'sync':
161
+ if default == "sync":
136
162
  assert fn() == 2
137
- elif default == 'async':
163
+ elif default == "async":
138
164
  assert asyncio.get_event_loop().run_until_complete(fn()) == 2
139
165
 
166
+
140
167
  async def sample_task(n):
141
168
  await asyncio.sleep(0.01)
142
169
  return n
143
170
 
171
+
144
172
  async def timeout_task(n):
145
173
  await asyncio.sleep(0.1)
146
174
  return n
147
175
 
176
+
148
177
  async def sample_exc(n):
149
- raise ValueError("Sample error")
178
+ raise ValueError("Sample error")
tests/test_abstract.py CHANGED
@@ -1,17 +1,20 @@
1
-
2
1
  import sys
3
2
 
4
3
  import pytest
5
4
 
6
5
  from a_sync.a_sync.abstract import ASyncABC
7
6
 
8
- _methods = '__a_sync_default_mode__', '__a_sync_flag_name__', '__a_sync_flag_value__'
7
+ _methods = "__a_sync_default_mode__", "__a_sync_flag_name__", "__a_sync_flag_value__"
9
8
  if sys.version_info >= (3, 12):
10
9
  _MIDDLE = "without an implementation for abstract methods"
11
10
  _methods = (f"'{method}'" for method in _methods)
12
11
  else:
13
12
  _MIDDLE = "with abstract methods"
14
13
 
14
+
15
15
  def test_abc_direct_init():
16
- with pytest.raises(TypeError, match=f"Can't instantiate abstract class ASyncABC {_MIDDLE} {', '.join(_methods)}"):
17
- ASyncABC()
16
+ with pytest.raises(
17
+ TypeError,
18
+ match=f"Can't instantiate abstract class ASyncABC {_MIDDLE} {', '.join(_methods)}",
19
+ ):
20
+ ASyncABC()
@@ -1,4 +1,3 @@
1
-
2
1
  import asyncio
3
2
 
4
3
  import a_sync
@@ -11,7 +10,10 @@ from tests.fixtures import sample_exc, sample_task, timeout_task
11
10
  async def test_as_completed_with_awaitables():
12
11
  tasks = [sample_task(i) for i in range(5)]
13
12
  results = [await result for result in a_sync.as_completed(tasks, aiter=False)]
14
- assert sorted(results) == list(range(5)), "Results should be in ascending order from 0 to 4"
13
+ assert sorted(results) == list(
14
+ range(5)
15
+ ), "Results should be in ascending order from 0 to 4"
16
+
15
17
 
16
18
  @pytest.mark.asyncio_cooperative
17
19
  async def test_as_completed_with_awaitables_aiter():
@@ -19,42 +21,61 @@ async def test_as_completed_with_awaitables_aiter():
19
21
  results = []
20
22
  async for result in a_sync.as_completed(tasks, aiter=True):
21
23
  results.append(result)
22
- assert sorted(results) == list(range(5)), "Results should be in ascending order from 0 to 4"
24
+ assert sorted(results) == list(
25
+ range(5)
26
+ ), "Results should be in ascending order from 0 to 4"
27
+
23
28
 
24
29
  @pytest.mark.asyncio_cooperative
25
30
  async def test_as_completed_with_mapping():
26
- tasks = {'task1': sample_task(1), 'task2': sample_task(2)}
31
+ tasks = {"task1": sample_task(1), "task2": sample_task(2)}
27
32
  results = {}
28
33
  for result in a_sync.as_completed(tasks, aiter=False):
29
34
  key, value = await result
30
35
  results[key] = value
31
- assert results == {'task1': 1, 'task2': 2}, "Results should match the input mapping"
36
+ assert results == {"task1": 1, "task2": 2}, "Results should match the input mapping"
37
+
32
38
 
33
39
  @pytest.mark.asyncio_cooperative
34
40
  async def test_as_completed_with_mapping_aiter():
35
- tasks = {'task1': sample_task(1), 'task2': sample_task(2)}
41
+ tasks = {"task1": sample_task(1), "task2": sample_task(2)}
36
42
  results = {}
37
43
  async for key, result in a_sync.as_completed(tasks, aiter=True):
38
44
  results[key] = result
39
- assert results == {'task1': 1, 'task2': 2}, "Results should match the input mapping"
45
+ assert results == {"task1": 1, "task2": 2}, "Results should match the input mapping"
46
+
40
47
 
41
48
  @pytest.mark.asyncio_cooperative
42
49
  async def test_as_completed_with_timeout():
43
50
  tasks = [timeout_task(i) for i in range(2)]
44
51
  with pytest.raises(asyncio.TimeoutError):
45
- [await result for result in a_sync.as_completed(tasks, aiter=False, timeout=0.05)]
52
+ [
53
+ await result
54
+ for result in a_sync.as_completed(tasks, aiter=False, timeout=0.05)
55
+ ]
56
+
46
57
 
47
58
  @pytest.mark.asyncio_cooperative
48
59
  async def test_as_completed_with_timeout_aiter():
49
60
  tasks = [timeout_task(i) for i in range(2)]
50
61
  with pytest.raises(asyncio.TimeoutError):
51
- [result async for result in a_sync.as_completed(tasks, aiter=True, timeout=0.05)]
62
+ [
63
+ result
64
+ async for result in a_sync.as_completed(tasks, aiter=True, timeout=0.05)
65
+ ]
66
+
52
67
 
53
68
  @pytest.mark.asyncio_cooperative
54
69
  async def test_as_completed_return_exceptions():
55
70
  tasks = [sample_exc(i) for i in range(1)]
56
- results = [await result for result in a_sync.as_completed(tasks, aiter=False, return_exceptions=True)]
57
- assert isinstance(results[0], ValueError), f"The result should be an exception {results}"
71
+ results = [
72
+ await result
73
+ for result in a_sync.as_completed(tasks, aiter=False, return_exceptions=True)
74
+ ]
75
+ assert isinstance(
76
+ results[0], ValueError
77
+ ), f"The result should be an exception {results}"
78
+
58
79
 
59
80
  @pytest.mark.asyncio_cooperative
60
81
  async def test_as_completed_return_exceptions_aiter():
@@ -64,11 +85,17 @@ async def test_as_completed_return_exceptions_aiter():
64
85
  results.append(result)
65
86
  assert isinstance(results[0], ValueError), "The result should be an exception"
66
87
 
88
+
67
89
  @pytest.mark.asyncio_cooperative
68
90
  async def test_as_completed_with_tqdm_disabled():
69
91
  tasks = [sample_task(i) for i in range(5)]
70
- results = [await result for result in a_sync.as_completed(tasks, aiter=False, tqdm=False)]
71
- assert sorted(results) == list(range(5)), "Results should be in ascending order from 0 to 4"
92
+ results = [
93
+ await result for result in a_sync.as_completed(tasks, aiter=False, tqdm=False)
94
+ ]
95
+ assert sorted(results) == list(
96
+ range(5)
97
+ ), "Results should be in ascending order from 0 to 4"
98
+
72
99
 
73
100
  @pytest.mark.asyncio_cooperative
74
101
  async def test_as_completed_with_tqdm_disabled_aiter():
@@ -76,23 +103,29 @@ async def test_as_completed_with_tqdm_disabled_aiter():
76
103
  results = []
77
104
  async for result in a_sync.as_completed(tasks, aiter=True, tqdm=False):
78
105
  results.append(result)
79
- assert sorted(results) == list(range(5)), "Results should be in ascending order from 0 to 4"
106
+ assert sorted(results) == list(
107
+ range(5)
108
+ ), "Results should be in ascending order from 0 to 4"
109
+
80
110
 
81
111
  @pytest.mark.asyncio_cooperative
82
112
  async def test_as_completed_with_mapping_and_return_exceptions():
83
- tasks = {'task1': sample_exc(1), 'task2': sample_task(2)}
113
+ tasks = {"task1": sample_exc(1), "task2": sample_task(2)}
84
114
  results = {}
85
115
  for result in a_sync.as_completed(tasks, return_exceptions=True, aiter=False):
86
116
  key, value = await result
87
117
  results[key] = value
88
- assert isinstance(results['task1'], ValueError), "Result should be ValueError"
89
- assert results['task2'] == 2, "Results should match the input mapping"
118
+ assert isinstance(results["task1"], ValueError), "Result should be ValueError"
119
+ assert results["task2"] == 2, "Results should match the input mapping"
120
+
90
121
 
91
122
  @pytest.mark.asyncio_cooperative
92
123
  async def test_as_completed_with_mapping_and_return_exceptions_aiter():
93
- tasks = {'task1': sample_exc(1), 'task2': sample_task(2)}
124
+ tasks = {"task1": sample_exc(1), "task2": sample_task(2)}
94
125
  results = {}
95
- async for key, result in a_sync.as_completed(tasks, return_exceptions=True, aiter=True):
126
+ async for key, result in a_sync.as_completed(
127
+ tasks, return_exceptions=True, aiter=True
128
+ ):
96
129
  results[key] = result
97
- assert isinstance(results['task1'], ValueError), "Result should be ValueError"
98
- assert results['task2'] == 2, "Results should match the input mapping"
130
+ assert isinstance(results["task1"], ValueError), "Result should be ValueError"
131
+ assert results["task2"] == 2, "Results should match the input mapping"
tests/test_base.py CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import asyncio
3
2
  import time
4
3
 
@@ -9,7 +8,14 @@ from a_sync.a_sync.base import ASyncGenericBase
9
8
  from a_sync.a_sync._meta import ASyncMeta
10
9
  from a_sync.a_sync.method import ASyncBoundMethodAsyncDefault
11
10
  from a_sync.exceptions import SyncModeInAsyncContextError
12
- from tests.fixtures import TestClass, TestInheritor, TestMeta, increment, TestSync, WrongThreadError
11
+ from tests.fixtures import (
12
+ TestClass,
13
+ TestInheritor,
14
+ TestMeta,
15
+ increment,
16
+ TestSync,
17
+ WrongThreadError,
18
+ )
13
19
 
14
20
 
15
21
  def test_base_direct_init():
@@ -17,9 +23,10 @@ def test_base_direct_init():
17
23
  ASyncGenericBase()
18
24
 
19
25
 
20
- classes = pytest.mark.parametrize('cls', [TestClass, TestSync, TestInheritor, TestMeta])
26
+ classes = pytest.mark.parametrize("cls", [TestClass, TestSync, TestInheritor, TestMeta])
27
+
28
+ both_modes = pytest.mark.parametrize("sync", [True, False])
21
29
 
22
- both_modes = pytest.mark.parametrize('sync', [True, False])
23
30
 
24
31
  @classes
25
32
  @both_modes
@@ -28,12 +35,13 @@ def test_inheritance(cls, sync: bool):
28
35
  assert isinstance(instance, ASyncGenericBase)
29
36
  assert isinstance(instance.__class__, ASyncMeta)
30
37
 
38
+
31
39
  @classes
32
40
  @increment
33
41
  def test_method_sync(cls: type, i: int):
34
42
  sync_instance = cls(i, sync=True)
35
43
  assert sync_instance.test_fn() == i
36
-
44
+
37
45
  # Can we override with kwargs?
38
46
  assert sync_instance.test_fn(sync=True) == i
39
47
  assert sync_instance.test_fn(asynchronous=False) == i
@@ -42,12 +50,27 @@ def test_method_sync(cls: type, i: int):
42
50
  if isinstance(sync_instance, TestSync):
43
51
  # this raises an assertion error inside of the test_fn execution. this is okay.
44
52
  with pytest.raises(WrongThreadError):
45
- asyncio.get_event_loop().run_until_complete(sync_instance.test_fn(sync=False))
53
+ asyncio.get_event_loop().run_until_complete(
54
+ sync_instance.test_fn(sync=False)
55
+ )
46
56
  with pytest.raises(WrongThreadError):
47
- asyncio.get_event_loop().run_until_complete(sync_instance.test_fn(asynchronous=True))
57
+ asyncio.get_event_loop().run_until_complete(
58
+ sync_instance.test_fn(asynchronous=True)
59
+ )
48
60
  else:
49
- assert isinstance(asyncio.get_event_loop().run_until_complete(sync_instance.test_fn(sync=False)), int)
50
- assert isinstance(asyncio.get_event_loop().run_until_complete(sync_instance.test_fn(asynchronous=True)), int)
61
+ assert isinstance(
62
+ asyncio.get_event_loop().run_until_complete(
63
+ sync_instance.test_fn(sync=False)
64
+ ),
65
+ int,
66
+ )
67
+ assert isinstance(
68
+ asyncio.get_event_loop().run_until_complete(
69
+ sync_instance.test_fn(asynchronous=True)
70
+ ),
71
+ int,
72
+ )
73
+
51
74
 
52
75
  @classes
53
76
  @increment
@@ -58,7 +81,7 @@ async def test_method_async(cls: type, i: int):
58
81
  # this raises an assertion error inside of the test_fn execution. this is okay.
59
82
  with pytest.raises(WrongThreadError):
60
83
  assert await async_instance.test_fn() == i
61
-
84
+
62
85
  # Can we override with kwargs?
63
86
  with pytest.raises(WrongThreadError):
64
87
  async_instance.test_fn(sync=True)
@@ -84,7 +107,7 @@ async def test_method_async(cls: type, i: int):
84
107
  def test_property_sync(cls: type, i: int):
85
108
  sync_instance = cls(i, sync=True)
86
109
  assert sync_instance.test_property == i * 2
87
-
110
+
88
111
  # Can we access hidden methods for properties?
89
112
  getter = sync_instance.__test_property__
90
113
  assert isinstance(getter, HiddenMethod), getter
@@ -92,6 +115,7 @@ def test_property_sync(cls: type, i: int):
92
115
  assert asyncio.iscoroutine(getter_coro), getter_coro
93
116
  assert asyncio.get_event_loop().run_until_complete(getter_coro) == i * 2
94
117
 
118
+
95
119
  @classes
96
120
  @increment
97
121
  @pytest.mark.asyncio_cooperative
@@ -117,7 +141,9 @@ def test_cached_property_sync(cls: type, i: int):
117
141
  assert sync_instance.test_cached_property == i * 3
118
142
  assert isinstance(sync_instance.test_cached_property, int)
119
143
  duration = time.time() - start
120
- assert duration < 3, "There is a 2 second sleep in 'test_cached_property' but it should only run once."
144
+ assert (
145
+ duration < 3
146
+ ), "There is a 2 second sleep in 'test_cached_property' but it should only run once."
121
147
 
122
148
  # Can we access hidden methods for properties?
123
149
  start = time.time()
@@ -128,9 +154,17 @@ def test_cached_property_sync(cls: type, i: int):
128
154
  assert asyncio.get_event_loop().run_until_complete(getter_coro) == i * 3
129
155
 
130
156
  # Can we override them too?
131
- assert asyncio.get_event_loop().run_until_complete(sync_instance.__test_cached_property__(sync=False)) == i * 3
157
+ assert (
158
+ asyncio.get_event_loop().run_until_complete(
159
+ sync_instance.__test_cached_property__(sync=False)
160
+ )
161
+ == i * 3
162
+ )
132
163
  duration = time.time() - start
133
- assert duration < 3, "There is a 2 second sleep in 'test_cached_property' but it should only run once."
164
+ assert (
165
+ duration < 3
166
+ ), "There is a 2 second sleep in 'test_cached_property' but it should only run once."
167
+
134
168
 
135
169
  @classes
136
170
  @increment
@@ -146,7 +180,7 @@ async def test_cached_property_async(cls: type, i: int):
146
180
  getter_coro = getter()
147
181
  assert asyncio.iscoroutine(getter_coro), getter_coro
148
182
  assert await getter_coro == i * 3
149
-
183
+
150
184
  # Can we override them too?
151
185
  with pytest.raises(SyncModeInAsyncContextError):
152
186
  getter(sync=True)
@@ -156,7 +190,9 @@ async def test_cached_property_async(cls: type, i: int):
156
190
  duration = time.time() - start
157
191
  # For TestSync, the duration can be higher because the calls execute inside of a threadpool which limits the amount of concurrency.
158
192
  target_duration = 5 if isinstance(async_instance, TestSync) else 2.1
159
- assert duration < target_duration, "There is a 2 second sleep in 'test_cached_property' but it should only run once."
193
+ assert (
194
+ duration < target_duration
195
+ ), "There is a 2 second sleep in 'test_cached_property' but it should only run once."
160
196
 
161
197
 
162
198
  @pytest.mark.asyncio_cooperative
@@ -166,6 +202,7 @@ async def test_asynchronous_context_manager():
166
202
  async def __aenter__(self):
167
203
  self.entered = True
168
204
  return self
205
+
169
206
  async def __aexit__(self, exc_type, exc_val, exc_tb):
170
207
  self.exited = True
171
208
 
@@ -173,6 +210,7 @@ async def test_asynchronous_context_manager():
173
210
  assert cm.entered
174
211
  assert cm.exited
175
212
 
213
+
176
214
  def test_synchronous_context_manager():
177
215
  # Can the implementation work with a context manager?
178
216
 
@@ -180,6 +218,7 @@ def test_synchronous_context_manager():
180
218
  def __enter__(self):
181
219
  self.entered = True
182
220
  return self
221
+
183
222
  def __exit__(self, exc_type, exc_val, exc_tb):
184
223
  self.exited = True
185
224
 
@@ -187,33 +226,41 @@ def test_synchronous_context_manager():
187
226
  assert cm.entered
188
227
  assert cm.exited
189
228
 
229
+
190
230
  @pytest.mark.asyncio_cooperative
191
231
  async def test_asynchronous_iteration():
192
232
  # Does the implementation screw anything up with aiteration?
193
233
  class ASyncObjectWithAiter(ASyncGenericBase):
194
234
  def __init__(self):
195
235
  self.count = 0
236
+
196
237
  def __aiter__(self):
197
238
  return self
239
+
198
240
  async def __anext__(self):
199
241
  if self.count < 3:
200
242
  self.count += 1
201
243
  return self.count
202
244
  raise StopAsyncIteration
245
+
203
246
  assert [item async for item in ASyncObjectWithAiter()] == [1, 2, 3]
204
247
 
248
+
205
249
  def test_synchronous_iteration():
206
250
  # Does the implementation screw anything up with iteration?
207
251
  class ASyncObjectWithIter(ASyncGenericBase):
208
252
  def __init__(self):
209
253
  self.count = 0
254
+
210
255
  def __iter__(self):
211
256
  return self
257
+
212
258
  def __next__(self):
213
259
  if self.count < 3:
214
260
  self.count += 1
215
261
  return self.count
216
262
  raise StopIteration
263
+
217
264
  assert list(ASyncObjectWithIter()) == [1, 2, 3]
218
265
 
219
266
 
@@ -223,13 +270,15 @@ class ClassWithGenFunc(ASyncGenericBase):
223
270
  yield 1
224
271
  yield 2
225
272
 
273
+
226
274
  def test_bound_generator_meta_sync():
227
275
  """Does the metaclass handle generator functions correctly?"""
228
276
  for _ in ClassWithGenFunc().generate():
229
277
  assert isinstance(_, int)
230
278
 
279
+
231
280
  @pytest.mark.asyncio_cooperative
232
281
  async def test_bound_generator_meta_async():
233
282
  """Does the metaclass handle generator functions correctly?"""
234
283
  async for _ in ClassWithGenFunc().generate():
235
- assert isinstance(_, int)
284
+ assert isinstance(_, int)