ez-a-sync 0.22.14__py3-none-any.whl → 0.22.16__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 +37 -5
  2. a_sync/__init__.py +53 -12
  3. a_sync/_smart.py +231 -28
  4. a_sync/_typing.py +112 -15
  5. a_sync/a_sync/__init__.py +35 -10
  6. a_sync/a_sync/_descriptor.py +248 -38
  7. a_sync/a_sync/_flags.py +78 -9
  8. a_sync/a_sync/_helpers.py +46 -13
  9. a_sync/a_sync/_kwargs.py +33 -8
  10. a_sync/a_sync/_meta.py +149 -28
  11. a_sync/a_sync/abstract.py +150 -28
  12. a_sync/a_sync/base.py +34 -16
  13. a_sync/a_sync/config.py +85 -14
  14. a_sync/a_sync/decorator.py +441 -139
  15. a_sync/a_sync/function.py +709 -147
  16. a_sync/a_sync/method.py +437 -110
  17. a_sync/a_sync/modifiers/__init__.py +85 -5
  18. a_sync/a_sync/modifiers/cache/__init__.py +116 -17
  19. a_sync/a_sync/modifiers/cache/memory.py +130 -20
  20. a_sync/a_sync/modifiers/limiter.py +101 -22
  21. a_sync/a_sync/modifiers/manager.py +142 -16
  22. a_sync/a_sync/modifiers/semaphores.py +121 -15
  23. a_sync/a_sync/property.py +383 -82
  24. a_sync/a_sync/singleton.py +44 -19
  25. a_sync/aliases.py +0 -1
  26. a_sync/asyncio/__init__.py +140 -1
  27. a_sync/asyncio/as_completed.py +213 -79
  28. a_sync/asyncio/create_task.py +70 -20
  29. a_sync/asyncio/gather.py +125 -58
  30. a_sync/asyncio/utils.py +3 -3
  31. a_sync/exceptions.py +248 -26
  32. a_sync/executor.py +164 -69
  33. a_sync/future.py +1227 -168
  34. a_sync/iter.py +173 -56
  35. a_sync/primitives/__init__.py +14 -2
  36. a_sync/primitives/_debug.py +72 -18
  37. a_sync/primitives/_loggable.py +41 -10
  38. a_sync/primitives/locks/__init__.py +5 -2
  39. a_sync/primitives/locks/counter.py +107 -38
  40. a_sync/primitives/locks/event.py +21 -7
  41. a_sync/primitives/locks/prio_semaphore.py +262 -63
  42. a_sync/primitives/locks/semaphore.py +138 -89
  43. a_sync/primitives/queue.py +601 -60
  44. a_sync/sphinx/__init__.py +0 -1
  45. a_sync/sphinx/ext.py +160 -50
  46. a_sync/task.py +313 -112
  47. a_sync/utils/__init__.py +12 -6
  48. a_sync/utils/iterators.py +170 -50
  49. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/METADATA +1 -1
  50. ez_a_sync-0.22.16.dist-info/RECORD +74 -0
  51. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/WHEEL +1 -1
  52. tests/conftest.py +1 -2
  53. tests/executor.py +250 -9
  54. tests/fixtures.py +61 -32
  55. tests/test_abstract.py +22 -4
  56. tests/test_as_completed.py +54 -21
  57. tests/test_base.py +264 -19
  58. tests/test_cache.py +31 -15
  59. tests/test_decorator.py +54 -28
  60. tests/test_executor.py +31 -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 +28 -11
  70. tests/test_task.py +162 -36
  71. ez_a_sync-0.22.14.dist-info/RECORD +0 -74
  72. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/LICENSE.txt +0 -0
  73. {ez_a_sync-0.22.14.dist-info → ez_a_sync-0.22.16.dist-info}/top_level.txt +0 -0
a_sync/a_sync/property.py CHANGED
@@ -1,4 +1,3 @@
1
-
2
1
  import functools
3
2
  import logging
4
3
 
@@ -9,8 +8,15 @@ from a_sync import _smart, exceptions
9
8
  from a_sync._typing import *
10
9
  from a_sync.a_sync import _helpers, config
11
10
  from a_sync.a_sync._descriptor import ASyncDescriptor
12
- from a_sync.a_sync.function import ASyncFunction, ASyncFunctionAsyncDefault, ASyncFunctionSyncDefault
13
- from a_sync.a_sync.method import ASyncBoundMethodAsyncDefault, ASyncMethodDescriptorAsyncDefault
11
+ from a_sync.a_sync.function import (
12
+ ASyncFunction,
13
+ ASyncFunctionAsyncDefault,
14
+ ASyncFunctionSyncDefault,
15
+ )
16
+ from a_sync.a_sync.method import (
17
+ ASyncBoundMethodAsyncDefault,
18
+ ASyncMethodDescriptorAsyncDefault,
19
+ )
14
20
 
15
21
  if TYPE_CHECKING:
16
22
  from a_sync.task import TaskMapping
@@ -18,63 +24,169 @@ if TYPE_CHECKING:
18
24
 
19
25
  logger = logging.getLogger(__name__)
20
26
 
27
+
21
28
  class _ASyncPropertyDescriptorBase(ASyncDescriptor[I, Tuple[()], T]):
29
+ """Base class for creating asynchronous properties.
30
+
31
+ This class provides the foundation for defining properties that can be accessed
32
+ both synchronously and asynchronously. It includes utility methods for common
33
+ operations such as `any`, `all`, `min`, `max`, and `sum`.
34
+ """
35
+
22
36
  any: ASyncFunction[AnyIterable[I], bool]
37
+ """An ASyncFunction that checks if any result is truthy."""
38
+
23
39
  all: ASyncFunction[AnyIterable[I], bool]
40
+ """An ASyncFunction that checks if all results are truthy."""
41
+
24
42
  min: ASyncFunction[AnyIterable[I], T]
43
+ """An ASyncFunction that returns the minimum result."""
44
+
25
45
  max: ASyncFunction[AnyIterable[I], T]
46
+ """An ASyncFunction that returns the maximum result."""
47
+
26
48
  sum: ASyncFunction[AnyIterable[I], T]
49
+ """An ASyncFunction that returns the sum of results."""
50
+
51
+ hidden_method_descriptor: "HiddenMethodDescriptor[T]"
52
+ """A descriptor for the hidden method."""
53
+
27
54
  __wrapped__: Callable[[I], T]
55
+ """The wrapped function or method."""
56
+
28
57
  __slots__ = "hidden_method_name", "hidden_method_descriptor", "_fget"
58
+
29
59
  def __init__(
30
- self,
31
- _fget: AsyncGetterFunction[I, T],
60
+ self,
61
+ _fget: AsyncGetterFunction[I, T],
32
62
  field_name: Optional[str] = None,
33
63
  **modifiers: Unpack[ModifierKwargs],
34
64
  ) -> None:
65
+ """Initializes the _ASyncPropertyDescriptorBase.
66
+
67
+ Args:
68
+ _fget: The function to be wrapped.
69
+ field_name: Optional name for the field. If not provided, the function's name will be used.
70
+ **modifiers: Additional modifier arguments.
71
+ """
35
72
  super().__init__(_fget, field_name, **modifiers)
36
73
  self.hidden_method_name = f"__{self.field_name}__"
37
74
  hidden_modifiers = dict(self.modifiers)
38
75
  hidden_modifiers["default"] = "async"
39
- self.hidden_method_descriptor: HiddenMethodDescriptor[T] = HiddenMethodDescriptor(self.get, self.hidden_method_name, **hidden_modifiers)
76
+ self.hidden_method_descriptor = HiddenMethodDescriptor(
77
+ self.get, self.hidden_method_name, **hidden_modifiers
78
+ )
40
79
  if asyncio.iscoroutinefunction(_fget):
41
80
  self._fget = self.__wrapped__
42
81
  else:
43
82
  self._fget = _helpers._asyncify(self.__wrapped__, self.modifiers.executor)
83
+
44
84
  @overload
45
- def __get__(self, instance: None, owner: Type[I]) -> Self:...
85
+ def __get__(self, instance: None, owner: Type[I]) -> Self: ...
46
86
  @overload
47
- def __get__(self, instance: I, owner: Type[I]) -> Awaitable[T]:...
48
- def __get__(self, instance: Optional[I], owner: Type[I]) -> Union[Self, Awaitable[T]]:
87
+ def __get__(self, instance: I, owner: Type[I]) -> Awaitable[T]: ...
88
+ def __get__(
89
+ self, instance: Optional[I], owner: Type[I]
90
+ ) -> Union[Self, Awaitable[T]]:
91
+ """Retrieves the property value, either synchronously or asynchronously.
92
+
93
+ Args:
94
+ instance: The instance from which the property is accessed.
95
+ owner: The owner class of the property.
96
+
97
+ Returns:
98
+ The property value, either as an awaitable or directly.
99
+ """
49
100
  if instance is None:
50
101
  return self
51
102
  awaitable = super().__get__(instance, owner)
52
103
  # if the user didn't specify a default behavior, we will defer to the instance
53
104
  if _is_a_sync_instance(instance):
54
- should_await = self.default == "sync" if self.default else instance.__a_sync_instance_should_await__
105
+ should_await = (
106
+ self.default == "sync"
107
+ if self.default
108
+ else instance.__a_sync_instance_should_await__
109
+ )
55
110
  else:
56
- should_await = self.default == "sync" if self.default else not asyncio.get_event_loop().is_running()
111
+ should_await = (
112
+ self.default == "sync"
113
+ if self.default
114
+ else not asyncio.get_event_loop().is_running()
115
+ )
57
116
  if should_await:
58
- logger.debug("awaiting awaitable for %s for instance: %s owner: %s", awaitable, self, instance, owner)
117
+ logger.debug(
118
+ "awaiting awaitable for %s for instance: %s owner: %s",
119
+ awaitable,
120
+ self,
121
+ instance,
122
+ owner,
123
+ )
59
124
  retval = _helpers._await(awaitable)
60
125
  else:
61
126
  retval = awaitable
62
- logger.debug("returning %s for %s for instance: %s owner: %s", retval, self, instance, owner)
127
+ logger.debug(
128
+ "returning %s for %s for instance: %s owner: %s",
129
+ retval,
130
+ self,
131
+ instance,
132
+ owner,
133
+ )
63
134
  return retval
135
+
64
136
  async def get(self, instance: I, owner: Optional[Type[I]] = None) -> T:
137
+ """Asynchronously retrieves the property value.
138
+
139
+ Args:
140
+ instance: The instance from which the property is accessed.
141
+ owner: The owner class of the property.
142
+
143
+ Returns:
144
+ The property value.
145
+ """
65
146
  if instance is None:
66
147
  raise ValueError(instance)
67
148
  logger.debug("awaiting %s for instance %s", self, instance)
68
149
  return await super().__get__(instance, owner)
69
- def map(self, instances: AnyIterable[I], owner: Optional[Type[I]] = None, concurrency: Optional[int] = None, name: str = "") -> "TaskMapping[I, T]":
150
+
151
+ def map(
152
+ self,
153
+ instances: AnyIterable[I],
154
+ owner: Optional[Type[I]] = None,
155
+ concurrency: Optional[int] = None,
156
+ name: str = "",
157
+ ) -> "TaskMapping[I, T]":
158
+ """Maps the property across multiple instances.
159
+
160
+ Args:
161
+ instances: An iterable of instances.
162
+ owner: The owner class of the property.
163
+ concurrency: Optional concurrency limit.
164
+ name: Optional name for the task mapping.
165
+
166
+ Returns:
167
+ A TaskMapping object.
168
+ """
70
169
  from a_sync.task import TaskMapping
170
+
71
171
  logger.debug("mapping %s to instances: %s owner: %s", self, instances, owner)
72
- return TaskMapping(self, instances, owner=owner, name=name or self.field_name, concurrency=concurrency)
172
+ return TaskMapping(
173
+ self,
174
+ instances,
175
+ owner=owner,
176
+ name=name or self.field_name,
177
+ concurrency=concurrency,
178
+ )
179
+
180
+
181
+ class ASyncPropertyDescriptor(
182
+ _ASyncPropertyDescriptorBase[I, T], ap.base.AsyncPropertyDescriptor
183
+ ):
184
+ """Descriptor class for asynchronous properties."""
73
185
 
74
- class ASyncPropertyDescriptor(_ASyncPropertyDescriptorBase[I, T], ap.base.AsyncPropertyDescriptor):
75
- pass
76
186
 
77
- class property(ASyncPropertyDescriptor[I, T]):...
187
+ class property(ASyncPropertyDescriptor[I, T]):
188
+ """Descriptor for defining properties that can be accessed both synchronously and asynchronously."""
189
+
78
190
 
79
191
  @final
80
192
  class ASyncPropertyDescriptorSyncDefault(property[I, T]):
@@ -91,13 +203,24 @@ class ASyncPropertyDescriptorSyncDefault(property[I, T]):
91
203
  min: ASyncFunctionSyncDefault[AnyIterable[I], T]
92
204
  max: ASyncFunctionSyncDefault[AnyIterable[I], T]
93
205
  sum: ASyncFunctionSyncDefault[AnyIterable[I], T]
206
+
94
207
  @overload
95
- def __get__(self, instance: None, owner: Type[I]) -> Self:...
208
+ def __get__(self, instance: None, owner: Type[I]) -> Self: ...
96
209
  @overload
97
- def __get__(self, instance: I, owner: Type[I]) -> T:...
210
+ def __get__(self, instance: I, owner: Type[I]) -> T: ...
98
211
  def __get__(self, instance: Optional[I], owner: Type[I]) -> Union[Self, T]:
212
+ """Retrieves the property value, either synchronously or asynchronously.
213
+
214
+ Args:
215
+ instance: The instance from which the property is accessed.
216
+ owner: The owner class of the property.
217
+
218
+ Returns:
219
+ The property value, either as an awaitable or directly.
220
+ """
99
221
  return _ASyncPropertyDescriptorBase.__get__(self, instance, owner)
100
222
 
223
+
101
224
  @final
102
225
  class ASyncPropertyDescriptorAsyncDefault(property[I, T]):
103
226
  """
@@ -116,93 +239,118 @@ class ASyncPropertyDescriptorAsyncDefault(property[I, T]):
116
239
 
117
240
 
118
241
  ASyncPropertyDecorator = Callable[[AnyGetterFunction[I, T]], property[I, T]]
119
- ASyncPropertyDecoratorSyncDefault = Callable[[AnyGetterFunction[I, T]], ASyncPropertyDescriptorSyncDefault[I, T]]
120
- ASyncPropertyDecoratorAsyncDefault = Callable[[AnyGetterFunction[I, T]], ASyncPropertyDescriptorAsyncDefault[I, T]]
242
+ ASyncPropertyDecoratorSyncDefault = Callable[
243
+ [AnyGetterFunction[I, T]], ASyncPropertyDescriptorSyncDefault[I, T]
244
+ ]
245
+ ASyncPropertyDecoratorAsyncDefault = Callable[
246
+ [AnyGetterFunction[I, T]], ASyncPropertyDescriptorAsyncDefault[I, T]
247
+ ]
248
+
121
249
 
122
250
  @overload
123
251
  def a_sync_property( # type: ignore [misc]
124
252
  func: Literal[None] = None,
125
253
  **modifiers: Unpack[ModifierKwargs],
126
- ) -> ASyncPropertyDecorator[I, T]:...
254
+ ) -> ASyncPropertyDecorator[I, T]: ...
255
+
127
256
 
128
257
  @overload
129
258
  def a_sync_property( # type: ignore [misc]
130
259
  func: AnyGetterFunction[I, T],
131
260
  **modifiers: Unpack[ModifierKwargs],
132
- ) -> ASyncPropertyDescriptor[I, T]:...
261
+ ) -> ASyncPropertyDescriptor[I, T]: ...
262
+
133
263
 
134
264
  @overload
135
265
  def a_sync_property( # type: ignore [misc]
136
266
  func: Literal[None],
137
267
  default: Literal["sync"],
138
268
  **modifiers: Unpack[ModifierKwargs],
139
- ) -> ASyncPropertyDecoratorSyncDefault[I, T]:...
269
+ ) -> ASyncPropertyDecoratorSyncDefault[I, T]: ...
270
+
140
271
 
141
272
  @overload
142
273
  def a_sync_property( # type: ignore [misc]
143
274
  func: Literal[None],
144
275
  default: Literal["sync"],
145
276
  **modifiers: Unpack[ModifierKwargs],
146
- ) -> ASyncPropertyDecoratorSyncDefault[I, T]:...
277
+ ) -> ASyncPropertyDecoratorSyncDefault[I, T]: ...
278
+
147
279
 
148
280
  @overload
149
281
  def a_sync_property( # type: ignore [misc]
150
282
  func: Literal[None],
151
283
  default: Literal["async"],
152
284
  **modifiers: Unpack[ModifierKwargs],
153
- ) -> ASyncPropertyDecoratorAsyncDefault[I, T]:...
285
+ ) -> ASyncPropertyDecoratorAsyncDefault[I, T]: ...
286
+
154
287
 
155
288
  @overload
156
289
  def a_sync_property( # type: ignore [misc]
157
290
  func: Literal[None],
158
291
  default: DefaultMode = config.DEFAULT_MODE,
159
292
  **modifiers: Unpack[ModifierKwargs],
160
- ) -> ASyncPropertyDecorator[I, T]:...
161
-
293
+ ) -> ASyncPropertyDecorator[I, T]: ...
294
+
295
+
162
296
  @overload
163
297
  def a_sync_property( # type: ignore [misc]
164
298
  default: Literal["sync"],
165
299
  **modifiers: Unpack[ModifierKwargs],
166
- ) -> ASyncPropertyDecoratorSyncDefault[I, T]:...
167
-
300
+ ) -> ASyncPropertyDecoratorSyncDefault[I, T]: ...
301
+
302
+
168
303
  @overload
169
304
  def a_sync_property( # type: ignore [misc]
170
305
  default: Literal["async"],
171
306
  **modifiers: Unpack[ModifierKwargs],
172
- ) -> ASyncPropertyDecoratorAsyncDefault[I, T]:...
173
-
307
+ ) -> ASyncPropertyDecoratorAsyncDefault[I, T]: ...
308
+
309
+
174
310
  @overload
175
311
  def a_sync_property( # type: ignore [misc]
176
312
  func: AnyGetterFunction[I, T],
177
313
  default: Literal["sync"],
178
314
  **modifiers: Unpack[ModifierKwargs],
179
- ) -> ASyncPropertyDescriptorSyncDefault[I, T]:...
180
-
315
+ ) -> ASyncPropertyDescriptorSyncDefault[I, T]: ...
316
+
317
+
181
318
  @overload
182
319
  def a_sync_property( # type: ignore [misc]
183
320
  func: AnyGetterFunction[I, T],
184
321
  default: Literal["async"],
185
322
  **modifiers: Unpack[ModifierKwargs],
186
- ) -> ASyncPropertyDescriptorAsyncDefault[I, T]:...
187
-
323
+ ) -> ASyncPropertyDescriptorAsyncDefault[I, T]: ...
324
+
325
+
188
326
  @overload
189
327
  def a_sync_property( # type: ignore [misc]
190
328
  func: AnyGetterFunction[I, T],
191
329
  default: DefaultMode = config.DEFAULT_MODE,
192
330
  **modifiers: Unpack[ModifierKwargs],
193
- ) -> ASyncPropertyDescriptor[I, T]:...
194
-
331
+ ) -> ASyncPropertyDescriptor[I, T]: ...
332
+
333
+
195
334
  def a_sync_property( # type: ignore [misc]
196
335
  func: Union[AnyGetterFunction[I, T], DefaultMode] = None,
197
336
  **modifiers: Unpack[ModifierKwargs],
198
337
  ) -> Union[
199
338
  ASyncPropertyDescriptor[I, T],
200
- ASyncPropertyDescriptorSyncDefault[I, T],
201
- ASyncPropertyDescriptorAsyncDefault[I, T],
339
+ ASyncPropertyDescriptorSyncDefault[I, T],
340
+ ASyncPropertyDescriptorAsyncDefault[I, T],
202
341
  ASyncPropertyDecorator[I, T],
203
342
  ASyncPropertyDecoratorSyncDefault[I, T],
204
343
  ASyncPropertyDecoratorAsyncDefault[I, T],
205
344
  ]:
345
+ """Decorator for creating properties that can be accessed both synchronously and asynchronously.
346
+
347
+ Args:
348
+ func: The function to be wrapped.
349
+ **modifiers: Additional modifier arguments.
350
+
351
+ Returns:
352
+ A property descriptor that supports both sync and async access.
353
+ """
206
354
  func, modifiers = _parse_args(func, modifiers)
207
355
  if modifiers.get("default") == "sync":
208
356
  descriptor_class = ASyncPropertyDescriptorSyncDefault
@@ -214,7 +362,9 @@ def a_sync_property( # type: ignore [misc]
214
362
  return decorator if func is None else decorator(func)
215
363
 
216
364
 
217
- class ASyncCachedPropertyDescriptor(_ASyncPropertyDescriptorBase[I, T], ap.cached.AsyncCachedPropertyDescriptor):
365
+ class ASyncCachedPropertyDescriptor(
366
+ _ASyncPropertyDescriptorBase[I, T], ap.cached.AsyncCachedPropertyDescriptor
367
+ ):
218
368
  """
219
369
  A descriptor class for dual-function sync/async cached properties.
220
370
 
@@ -223,21 +373,42 @@ class ASyncCachedPropertyDescriptor(_ASyncPropertyDescriptorBase[I, T], ap.cache
223
373
  """
224
374
 
225
375
  __slots__ = "_fset", "_fdel", "__async_property__"
376
+
226
377
  def __init__(
227
- self,
228
- _fget: AsyncGetterFunction[I, T],
229
- _fset = None,
230
- _fdel = None,
231
- field_name=None,
378
+ self,
379
+ _fget: AsyncGetterFunction[I, T],
380
+ _fset=None,
381
+ _fdel=None,
382
+ field_name=None,
232
383
  **modifiers: Unpack[ModifierKwargs],
233
384
  ) -> None:
385
+ """Initializes the ASyncCachedPropertyDescriptor.
386
+
387
+ Args:
388
+ _fget: The function to be wrapped.
389
+ _fset: Optional setter function for the property.
390
+ _fdel: Optional deleter function for the property.
391
+ field_name: Optional name for the field. If not provided, the function's name will be used.
392
+ **modifiers: Additional modifier arguments.
393
+ """
234
394
  super().__init__(_fget, field_name, **modifiers)
235
- self._check_method_sync(_fset, 'setter')
236
- self._check_method_sync(_fdel, 'deleter')
395
+ self._check_method_sync(_fset, "setter")
237
396
  self._fset = _fset
397
+ """Optional setter function for the property."""
398
+
399
+ self._check_method_sync(_fdel, "deleter")
238
400
  self._fdel = _fdel
401
+ """Optional deleter function for the property."""
239
402
 
240
403
  def get_lock(self, instance: I) -> "asyncio.Task[T]":
404
+ """Retrieves the lock for the property.
405
+
406
+ Args:
407
+ instance: The instance from which the property is accessed.
408
+
409
+ Returns:
410
+ An asyncio Task representing the lock.
411
+ """
241
412
  instance_state = self.get_instance_state(instance)
242
413
  task = instance_state.lock[self.field_name]
243
414
  if isinstance(task, asyncio.Lock):
@@ -245,11 +416,25 @@ class ASyncCachedPropertyDescriptor(_ASyncPropertyDescriptorBase[I, T], ap.cache
245
416
  task = asyncio.create_task(self._fget(instance))
246
417
  instance_state.lock[self.field_name] = task
247
418
  return task
248
-
419
+
249
420
  def pop_lock(self, instance: I) -> None:
421
+ """Removes the lock for the property.
422
+
423
+ Args:
424
+ instance: The instance from which the property is accessed.
425
+ """
250
426
  self.get_instance_state(instance).lock.pop(self.field_name, None)
251
427
 
252
428
  def get_loader(self, instance: I) -> Callable[[], T]:
429
+ """Retrieves the loader function for the property.
430
+
431
+ Args:
432
+ instance: The instance from which the property is accessed.
433
+
434
+ Returns:
435
+ A callable that loads the property value.
436
+ """
437
+
253
438
  @functools.wraps(self._fget)
254
439
  async def load_value():
255
440
  inner_task = self.get_lock(instance)
@@ -261,9 +446,13 @@ class ASyncCachedPropertyDescriptor(_ASyncPropertyDescriptorBase[I, T], ap.cache
261
446
  self.__set__(instance, value)
262
447
  self.pop_lock(instance)
263
448
  return value
449
+
264
450
  return load_value
265
-
266
- class cached_property(ASyncCachedPropertyDescriptor[I, T]):...
451
+
452
+
453
+ class cached_property(ASyncCachedPropertyDescriptor[I, T]):
454
+ """Descriptor for defining cached properties that can be accessed both synchronously and asynchronously."""
455
+
267
456
 
268
457
  @final
269
458
  class ASyncCachedPropertyDescriptorSyncDefault(cached_property[I, T]):
@@ -275,11 +464,21 @@ class ASyncCachedPropertyDescriptorSyncDefault(cached_property[I, T]):
275
464
  """
276
465
 
277
466
  default: Literal["sync"]
467
+
278
468
  @overload
279
- def __get__(self, instance: None, owner: Type[I]) -> Self:...
469
+ def __get__(self, instance: None, owner: Type[I]) -> Self: ...
280
470
  @overload
281
- def __get__(self, instance: I, owner: Type[I]) -> T:...
471
+ def __get__(self, instance: I, owner: Type[I]) -> T: ...
282
472
  def __get__(self, instance: Optional[I], owner: Type[I]) -> Union[Self, T]:
473
+ """Retrieves the cached property value, either synchronously or asynchronously.
474
+
475
+ Args:
476
+ instance: The instance from which the property is accessed.
477
+ owner: The owner class of the property.
478
+
479
+ Returns:
480
+ The cached property value, either as an awaitable or directly.
481
+ """
283
482
  return _ASyncPropertyDescriptorBase.__get__(self, instance, owner)
284
483
 
285
484
 
@@ -294,126 +493,190 @@ class ASyncCachedPropertyDescriptorAsyncDefault(cached_property[I, T]):
294
493
 
295
494
  default: Literal["async"]
296
495
 
297
- ASyncCachedPropertyDecorator = Callable[[AnyGetterFunction[I, T]], cached_property[I, T]]
298
- ASyncCachedPropertyDecoratorSyncDefault = Callable[[AnyGetterFunction[I, T]], ASyncCachedPropertyDescriptorSyncDefault[I, T]]
299
- ASyncCachedPropertyDecoratorAsyncDefault = Callable[[AnyGetterFunction[I, T]], ASyncCachedPropertyDescriptorAsyncDefault[I, T]]
496
+
497
+ ASyncCachedPropertyDecorator = Callable[
498
+ [AnyGetterFunction[I, T]], cached_property[I, T]
499
+ ]
500
+ ASyncCachedPropertyDecoratorSyncDefault = Callable[
501
+ [AnyGetterFunction[I, T]], ASyncCachedPropertyDescriptorSyncDefault[I, T]
502
+ ]
503
+ ASyncCachedPropertyDecoratorAsyncDefault = Callable[
504
+ [AnyGetterFunction[I, T]], ASyncCachedPropertyDescriptorAsyncDefault[I, T]
505
+ ]
506
+
300
507
 
301
508
  @overload
302
509
  def a_sync_cached_property( # type: ignore [misc]
303
510
  func: Literal[None] = None,
304
511
  **modifiers: Unpack[ModifierKwargs],
305
- ) -> ASyncCachedPropertyDecorator[I, T]:...
512
+ ) -> ASyncCachedPropertyDecorator[I, T]: ...
513
+
306
514
 
307
515
  @overload
308
516
  def a_sync_cached_property( # type: ignore [misc]
309
517
  func: AnyGetterFunction[I, T],
310
518
  **modifiers: Unpack[ModifierKwargs],
311
- ) -> ASyncCachedPropertyDescriptor[I, T]:...
519
+ ) -> ASyncCachedPropertyDescriptor[I, T]: ...
520
+
312
521
 
313
522
  @overload
314
523
  def a_sync_cached_property( # type: ignore [misc]
315
524
  func: Literal[None],
316
525
  default: Literal["sync"],
317
526
  **modifiers: Unpack[ModifierKwargs],
318
- ) -> ASyncCachedPropertyDecoratorSyncDefault[I, T]:...
527
+ ) -> ASyncCachedPropertyDecoratorSyncDefault[I, T]: ...
528
+
319
529
 
320
530
  @overload
321
531
  def a_sync_cached_property( # type: ignore [misc]
322
532
  func: Literal[None],
323
533
  default: Literal["async"],
324
534
  **modifiers: Unpack[ModifierKwargs],
325
- ) -> ASyncCachedPropertyDecoratorAsyncDefault[I, T]:...
535
+ ) -> ASyncCachedPropertyDecoratorAsyncDefault[I, T]: ...
536
+
326
537
 
327
538
  @overload
328
539
  def a_sync_cached_property( # type: ignore [misc]
329
540
  func: Literal[None],
330
541
  default: DefaultMode,
331
542
  **modifiers: Unpack[ModifierKwargs],
332
- ) -> ASyncCachedPropertyDecorator[I, T]:...
543
+ ) -> ASyncCachedPropertyDecorator[I, T]: ...
544
+
333
545
 
334
546
  @overload
335
547
  def a_sync_cached_property( # type: ignore [misc]
336
548
  default: Literal["sync"],
337
549
  **modifiers: Unpack[ModifierKwargs],
338
- ) -> ASyncCachedPropertyDecoratorSyncDefault[I, T]:...
550
+ ) -> ASyncCachedPropertyDecoratorSyncDefault[I, T]: ...
551
+
339
552
 
340
553
  @overload
341
554
  def a_sync_cached_property( # type: ignore [misc]
342
555
  default: Literal["async"],
343
556
  **modifiers: Unpack[ModifierKwargs],
344
- ) -> ASyncCachedPropertyDecoratorAsyncDefault[I, T]:...
345
-
557
+ ) -> ASyncCachedPropertyDecoratorAsyncDefault[I, T]: ...
558
+
559
+
346
560
  @overload
347
561
  def a_sync_cached_property( # type: ignore [misc]
348
562
  func: AnyGetterFunction[I, T],
349
563
  default: Literal["sync"],
350
564
  **modifiers: Unpack[ModifierKwargs],
351
- ) -> ASyncCachedPropertyDescriptorSyncDefault[I, T]:...
565
+ ) -> ASyncCachedPropertyDescriptorSyncDefault[I, T]: ...
566
+
352
567
 
353
568
  @overload
354
569
  def a_sync_cached_property( # type: ignore [misc]
355
570
  func: AnyGetterFunction[I, T],
356
571
  default: Literal["async"],
357
572
  **modifiers: Unpack[ModifierKwargs],
358
- ) -> ASyncCachedPropertyDescriptorAsyncDefault[I, T]:...
573
+ ) -> ASyncCachedPropertyDescriptorAsyncDefault[I, T]: ...
574
+
359
575
 
360
576
  @overload
361
577
  def a_sync_cached_property( # type: ignore [misc]
362
578
  func: AnyGetterFunction[I, T],
363
579
  default: DefaultMode = config.DEFAULT_MODE,
364
580
  **modifiers: Unpack[ModifierKwargs],
365
- ) -> ASyncCachedPropertyDescriptor[I, T]:...
366
-
581
+ ) -> ASyncCachedPropertyDescriptor[I, T]: ...
582
+
583
+
367
584
  def a_sync_cached_property( # type: ignore [misc]
368
585
  func: Optional[AnyGetterFunction[I, T]] = None,
369
586
  **modifiers: Unpack[ModifierKwargs],
370
587
  ) -> Union[
371
588
  ASyncCachedPropertyDescriptor[I, T],
372
- ASyncCachedPropertyDescriptorSyncDefault[I, T],
373
- ASyncCachedPropertyDescriptorAsyncDefault[I, T],
589
+ ASyncCachedPropertyDescriptorSyncDefault[I, T],
590
+ ASyncCachedPropertyDescriptorAsyncDefault[I, T],
374
591
  ASyncCachedPropertyDecorator[I, T],
375
592
  ASyncCachedPropertyDecoratorSyncDefault[I, T],
376
593
  ASyncCachedPropertyDecoratorAsyncDefault[I, T],
377
594
  ]:
595
+ """Decorator for creating cached properties that can be accessed both synchronously and asynchronously.
596
+
597
+ Args:
598
+ func: The function to be wrapped.
599
+ **modifiers: Additional modifier arguments.
600
+
601
+ Returns:
602
+ A cached property descriptor that supports both sync and async access.
603
+ """
378
604
  func, modifiers = _parse_args(func, modifiers)
379
605
  if modifiers.get("default") == "sync":
380
606
  descriptor_class = ASyncCachedPropertyDescriptorSyncDefault
381
- elif modifiers.get("default") == "sync":
607
+ elif modifiers.get("default") == "async":
382
608
  descriptor_class = ASyncCachedPropertyDescriptorAsyncDefault
383
609
  else:
384
610
  descriptor_class = ASyncCachedPropertyDescriptor
385
611
  decorator = functools.partial(descriptor_class, **modifiers)
386
612
  return decorator if func is None else decorator(func)
387
613
 
614
+
388
615
  @final
389
616
  class HiddenMethod(ASyncBoundMethodAsyncDefault[I, Tuple[()], T]):
617
+ """Represents a hidden method for asynchronous properties.
618
+
619
+ This class is used internally to manage hidden methods associated with
620
+ asynchronous properties.
621
+ """
622
+
390
623
  def __init__(
391
- self,
392
- instance: I,
393
- unbound: AnyFn[Concatenate[I, P], T],
624
+ self,
625
+ instance: I,
626
+ unbound: AnyFn[Concatenate[I, P], T],
394
627
  async_def: bool,
395
628
  field_name: str,
396
629
  **modifiers: Unpack[ModifierKwargs],
397
630
  ) -> None:
631
+ """Initializes the HiddenMethod.
632
+
633
+ Args:
634
+ instance: The instance to which the method is bound.
635
+ unbound: The unbound function to be wrapped.
636
+ async_def: Indicates if the method is asynchronous.
637
+ field_name: The name of the field associated with the method.
638
+ **modifiers: Additional modifier arguments.
639
+ """
398
640
  super().__init__(instance, unbound, async_def, **modifiers)
399
641
  self.__name__ = field_name
642
+ """The name of the hidden method."""
643
+
400
644
  def __repr__(self) -> str:
645
+ """Returns a string representation of the HiddenMethod."""
401
646
  instance_type = type(self.__self__)
402
647
  return f"<{self.__class__.__name__} for property {instance_type.__module__}.{instance_type.__name__}.{self.__name__[2:-2]} bound to {self.__self__}>"
648
+
403
649
  def _should_await(self, kwargs: dict) -> bool:
650
+ """Determines if the method should be awaited.
651
+
652
+ Args:
653
+ kwargs: The keyword arguments passed to the method.
654
+
655
+ Returns:
656
+ A boolean indicating if the method should be awaited.
657
+ """
404
658
  try:
405
659
  return self.__self__.__a_sync_should_await_from_kwargs__(kwargs)
406
660
  except (AttributeError, exceptions.NoFlagsFound):
407
661
  return False
662
+
408
663
  def __await__(self) -> Generator[Any, None, T]:
664
+ """Returns an awaitable for the method."""
409
665
  return self(sync=False).__await__()
410
666
 
667
+
411
668
  @final
412
669
  class HiddenMethodDescriptor(ASyncMethodDescriptorAsyncDefault[I, Tuple[()], T]):
670
+ """Descriptor for hidden methods associated with asynchronous properties.
671
+
672
+ This class is used internally to manage hidden methods associated with
673
+ asynchronous properties.
674
+ """
675
+
413
676
  def __init__(
414
- self,
415
- _fget: AnyFn[Concatenate[I, P], Awaitable[T]],
416
- field_name: Optional[str] = None,
677
+ self,
678
+ _fget: AnyFn[Concatenate[I, P], Awaitable[T]],
679
+ field_name: Optional[str] = None,
417
680
  **modifiers: Unpack[ModifierKwargs],
418
681
  ) -> None:
419
682
  """
@@ -434,30 +697,68 @@ class HiddenMethodDescriptor(ASyncMethodDescriptorAsyncDefault[I, Tuple[()], T])
434
697
  self.__doc__ += f"A :class:`HiddenMethodDescriptor` for :meth:`{self.__wrapped__.__qualname__}`."
435
698
  if self.__wrapped__.__doc__:
436
699
  self.__doc__ += f"\n\nThe original docstring for :meth:`~{self.__wrapped__.__qualname__}` is shown below:\n\n{self.__wrapped__.__doc__}"
700
+
437
701
  def __get__(self, instance: I, owner: Type[I]) -> HiddenMethod[I, T]:
702
+ """Retrieves the hidden method for the property.
703
+
704
+ Args:
705
+ instance: The instance from which the method is accessed.
706
+ owner: The owner class of the method.
707
+
708
+ Returns:
709
+ The hidden method.
710
+ """
438
711
  if instance is None:
439
712
  return self
440
713
  try:
441
714
  bound = instance.__dict__[self.field_name]
442
715
  bound._cache_handle.cancel()
443
716
  except KeyError:
444
- bound = HiddenMethod(instance, self.__wrapped__, self.__is_async_def__, self.field_name, **self.modifiers)
717
+ bound = HiddenMethod(
718
+ instance,
719
+ self.__wrapped__,
720
+ self.__is_async_def__,
721
+ self.field_name,
722
+ **self.modifiers,
723
+ )
445
724
  instance.__dict__[self.field_name] = bound
446
725
  logger.debug("new hidden method: %s", bound)
447
726
  bound._cache_handle = self._get_cache_handle(instance)
448
727
  return bound
449
728
 
729
+
450
730
  def _is_a_sync_instance(instance: object) -> bool:
731
+ """Checks if an instance is an ASync instance.
732
+
733
+ Args:
734
+ instance: The instance to check.
735
+
736
+ Returns:
737
+ A boolean indicating if the instance is an ASync instance.
738
+ """
451
739
  try:
452
740
  return instance.__is_a_sync_instance__ # type: ignore [attr-defined]
453
741
  except AttributeError:
454
742
  from a_sync.a_sync.abstract import ASyncABC
743
+
455
744
  is_a_sync = isinstance(instance, ASyncABC)
456
745
  instance.__is_a_sync_instance__ = is_a_sync
457
746
  return is_a_sync
458
747
 
459
- def _parse_args(func: Union[None, DefaultMode, AsyncGetterFunction[I, T]], modifiers: ModifierKwargs) -> Tuple[Optional[AsyncGetterFunction[I, T]], ModifierKwargs]:
460
- if func in ['sync', 'async']:
461
- modifiers['default'] = func
748
+
749
+ def _parse_args(
750
+ func: Union[None, DefaultMode, AsyncGetterFunction[I, T]], modifiers: ModifierKwargs
751
+ ) -> Tuple[Optional[AsyncGetterFunction[I, T]], ModifierKwargs]:
752
+ """Parses the arguments for the property decorators.
753
+
754
+ Args:
755
+ func: The function to be wrapped.
756
+ modifiers: Additional modifier arguments.
757
+
758
+ Returns:
759
+ A tuple containing the parsed function and modifiers.
760
+ """
761
+ if func in ["sync", "async"]:
762
+ modifiers["default"] = func
462
763
  func = None
463
764
  return func, modifiers