xoscar 0.1.4__cp39-cp39-win_amd64.whl → 0.2.1__cp39-cp39-win_amd64.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 xoscar might be problematic. Click here for more details.

xoscar/__init__.py CHANGED
@@ -32,6 +32,7 @@ from .api import (
32
32
  setup_cluster,
33
33
  wait_actor_pool_recovered,
34
34
  get_pool_config,
35
+ generator,
35
36
  )
36
37
  from .backends import allocate_strategy
37
38
  from .backends.pool import MainActorPoolType
Binary file
xoscar/api.py CHANGED
@@ -15,9 +15,26 @@
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
+ import asyncio
19
+ import functools
20
+ import inspect
21
+ import logging
22
+ import threading
23
+ import uuid
18
24
  from collections import defaultdict
19
25
  from numbers import Number
20
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Type, Union
26
+ from typing import (
27
+ TYPE_CHECKING,
28
+ Any,
29
+ Dict,
30
+ Generic,
31
+ List,
32
+ Optional,
33
+ Tuple,
34
+ Type,
35
+ TypeVar,
36
+ Union,
37
+ )
21
38
  from urllib.parse import urlparse
22
39
 
23
40
  from .aio import AioFileObject
@@ -29,6 +46,8 @@ if TYPE_CHECKING:
29
46
  from .backends.config import ActorPoolConfig
30
47
  from .backends.pool import MainActorPoolType
31
48
 
49
+ logger = logging.getLogger(__name__)
50
+
32
51
 
33
52
  async def create_actor(
34
53
  actor_cls: Type, *args, uid=None, address=None, **kwargs
@@ -271,6 +290,61 @@ def setup_cluster(address_to_resources: Dict[str, Dict[str, Number]]):
271
290
  get_backend(scheme).get_driver_cls().setup_cluster(address_resources)
272
291
 
273
292
 
293
+ T = TypeVar("T")
294
+
295
+
296
+ class IteratorWrapper(Generic[T]):
297
+ def __init__(self, uid: str, actor_addr: str, actor_uid: str):
298
+ self._uid = uid
299
+ self._actor_addr = actor_addr
300
+ self._actor_uid = actor_uid
301
+ self._actor_ref = None
302
+ self._gc_destroy = True
303
+
304
+ async def destroy(self):
305
+ if self._actor_ref is None:
306
+ self._actor_ref = await actor_ref(
307
+ address=self._actor_addr, uid=self._actor_uid
308
+ )
309
+ assert self._actor_ref is not None
310
+ return await self._actor_ref.__xoscar_destroy_generator__(self._uid)
311
+
312
+ def __del__(self):
313
+ # It's not a good idea to spawn a new thread and join in __del__,
314
+ # but currently it's the only way to GC the generator.
315
+ # TODO(codingl2k1): This __del__ may hangs if the program is exiting.
316
+ if self._gc_destroy:
317
+ thread = threading.Thread(
318
+ target=asyncio.run, args=(self.destroy(),), daemon=True
319
+ )
320
+ thread.start()
321
+ thread.join()
322
+
323
+ def __aiter__(self):
324
+ return self
325
+
326
+ def __getstate__(self):
327
+ # Transfer gc destroy during serialization.
328
+ state = self.__dict__.copy()
329
+ state["_gc_destroy"] = True
330
+ self._gc_destroy = False
331
+ return state
332
+
333
+ async def __anext__(self) -> T:
334
+ if self._actor_ref is None:
335
+ self._actor_ref = await actor_ref(
336
+ address=self._actor_addr, uid=self._actor_uid
337
+ )
338
+ try:
339
+ assert self._actor_ref is not None
340
+ return await self._actor_ref.__xoscar_next__(self._uid)
341
+ except Exception as e:
342
+ if "StopIteration" in str(e):
343
+ raise StopAsyncIteration
344
+ else:
345
+ raise
346
+
347
+
274
348
  class AsyncActorMixin:
275
349
  @classmethod
276
350
  def default_uid(cls):
@@ -282,6 +356,10 @@ class AsyncActorMixin:
282
356
  except KeyError:
283
357
  return super().__new__(cls, *args, **kwargs)
284
358
 
359
+ def __init__(self, *args, **kwargs) -> None:
360
+ super().__init__()
361
+ self._generators: Dict[str, IteratorWrapper] = {}
362
+
285
363
  async def __post_create__(self):
286
364
  """
287
365
  Method called after actor creation
@@ -305,6 +383,93 @@ class AsyncActorMixin:
305
383
  """
306
384
  return await super().__on_receive__(message) # type: ignore
307
385
 
386
+ async def __xoscar_next__(self, generator_uid: str) -> Any:
387
+ """
388
+ Iter the next of generator.
389
+
390
+ Parameters
391
+ ----------
392
+ generator_uid: str
393
+ The uid of generator
394
+
395
+ Returns
396
+ -------
397
+ The next value of generator
398
+ """
399
+
400
+ def _wrapper(_gen):
401
+ try:
402
+ return next(_gen)
403
+ except StopIteration:
404
+ return stop
405
+
406
+ async def _async_wrapper(_gen):
407
+ try:
408
+ # anext is only available for Python >= 3.10
409
+ return await _gen.__anext__() # noqa: F821
410
+ except StopAsyncIteration:
411
+ return stop
412
+
413
+ if gen := self._generators.get(generator_uid):
414
+ stop = object()
415
+ try:
416
+ if inspect.isgenerator(gen):
417
+ r = await asyncio.to_thread(_wrapper, gen)
418
+ elif inspect.isasyncgen(gen):
419
+ r = await asyncio.create_task(_async_wrapper(gen))
420
+ else:
421
+ raise Exception(
422
+ f"The generator {generator_uid} should be a generator or an async generator, "
423
+ f"but a {type(gen)} is got."
424
+ )
425
+ except Exception as e:
426
+ logger.exception(
427
+ f"Destroy generator {generator_uid} due to an error encountered."
428
+ )
429
+ await self.__xoscar_destroy_generator__(generator_uid)
430
+ del gen # Avoid exception hold generator reference.
431
+ raise e
432
+ if r is stop:
433
+ await self.__xoscar_destroy_generator__(generator_uid)
434
+ del gen # Avoid exception hold generator reference.
435
+ raise Exception("StopIteration")
436
+ else:
437
+ return r
438
+ else:
439
+ raise RuntimeError(f"No iterator with id: {generator_uid}")
440
+
441
+ async def __xoscar_destroy_generator__(self, generator_uid: str):
442
+ """
443
+ Destroy the generator.
444
+
445
+ Parameters
446
+ ----------
447
+ generator_uid: str
448
+ The uid of generator
449
+ """
450
+ logger.debug("Destroy generator: %s", generator_uid)
451
+ self._generators.pop(generator_uid, None)
452
+
453
+
454
+ def generator(func):
455
+ need_to_thread = not asyncio.iscoroutinefunction(func)
456
+
457
+ @functools.wraps(func)
458
+ async def _wrapper(self, *args, **kwargs):
459
+ if need_to_thread:
460
+ r = await asyncio.to_thread(func, self, *args, **kwargs)
461
+ else:
462
+ r = await func(self, *args, **kwargs)
463
+ if inspect.isgenerator(r) or inspect.isasyncgen(r):
464
+ gen_uid = uuid.uuid1().hex
465
+ logger.debug("Create generator: %s", gen_uid)
466
+ self._generators[gen_uid] = r
467
+ return IteratorWrapper(gen_uid, self.address, self.uid)
468
+ else:
469
+ return r
470
+
471
+ return _wrapper
472
+
308
473
 
309
474
  class Actor(AsyncActorMixin, _Actor):
310
475
  pass
Binary file
xoscar/collective/uv.dll CHANGED
Binary file
Binary file
Binary file
xoscar/core.pyx CHANGED
@@ -127,7 +127,7 @@ cdef class ActorRef:
127
127
  return create_actor_ref, (self.address, self.uid)
128
128
 
129
129
  def __getattr__(self, item):
130
- if item.startswith('_'):
130
+ if item.startswith('_') and item not in ["__xoscar_next__", "__xoscar_destroy_generator__"]:
131
131
  return object.__getattribute__(self, item)
132
132
 
133
133
  try:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xoscar
3
- Version: 0.1.4
3
+ Version: 0.2.1
4
4
  Summary: Python actor framework for heterogeneous computing.
5
5
  Home-page: http://github.com/xorbitsai/xoscar
6
6
  Author: Qin Xuye
@@ -1,18 +1,18 @@
1
- xoscar/__init__.py,sha256=rrre56CmXi2ItpdBru0sMQRvSxuLa-Mj18a1E481Bmk,1769
2
- xoscar/_utils.cp39-win_amd64.pyd,sha256=gbnV8ZFf9Hyk-DbqW6sVk4KZkp3Vd_-y1nU3tsMFiKM,117248
1
+ xoscar/__init__.py,sha256=MfWK519G_Rs8z-zkT5HdrEfJcPa6p6vqU5uvdTJTH5Y,1785
2
+ xoscar/_utils.cp39-win_amd64.pyd,sha256=y_lakm1_XS9rbBHxSVQUnELVHYIQPWbCR-VsIdXoHow,117248
3
3
  xoscar/_utils.pxd,sha256=rlNbTg5lhXA-jCOLksqF4jhUlNn0xw2jx1HxdLa34pc,1193
4
4
  xoscar/_utils.pyx,sha256=5Wvind3AQ3JaMK7Zv9SjhiPO6LEol2hW7_fMncn69go,7300
5
5
  xoscar/_version.py,sha256=bsfCVAo_o9LkiP3AjPsP4SRRqhjuS0t4D1WGJPzbdls,24412
6
- xoscar/api.py,sha256=j0LVDNighYZc2xds69qKvhPavWb7QTBDyrk4sbp3Hmw,8652
6
+ xoscar/api.py,sha256=B5oXv4vgMxMteh1YNaBmNFDrUFmYa_dCdzfaWwwZnCo,13820
7
7
  xoscar/backend.py,sha256=8G5JwjoOT6Q2slb11eXNApxgcmvNQUCdQzkoIMDwLcQ,1917
8
8
  xoscar/batch.py,sha256=Jk5BSpvMFAV9DrRy0a9tgPvIo_dt8cbJReZBL0cnOPc,8128
9
9
  xoscar/constants.py,sha256=H9ntCahBz5nKO-A6rkrGKy4WB2kNaLZAytkDajKIXqM,780
10
- xoscar/context.cp39-win_amd64.pyd,sha256=qf0H5vkKXCjzhnychCuqIhJJFTtf7J9hX5ml9Zz_5Aw,158208
10
+ xoscar/context.cp39-win_amd64.pyd,sha256=g7Y7boTpX5k3oRnHai3wF7pFjNYEBpTnITUpIFEZ4po,158208
11
11
  xoscar/context.pxd,sha256=6n6IAbmArSRq8EjcsbS6npW8xP1jI0qOoS1fF0oyj-o,746
12
12
  xoscar/context.pyx,sha256=FOJVerGOvxe2USryXEQA0rpaFX_ScxISH6QWKUcahY8,11310
13
- xoscar/core.cp39-win_amd64.pyd,sha256=gfG3xtD61Va_YoD5vCivaCrNQfWp22mVMvrnpNiFmb0,333312
13
+ xoscar/core.cp39-win_amd64.pyd,sha256=1VzFHAHfnNwhB0GtcxIXxFofh9gunvUWlU84fKnpZPU,333824
14
14
  xoscar/core.pxd,sha256=dGv62H92PFG98SVILuF641kY-NWFEt1FYqqOX3WY5RQ,1330
15
- xoscar/core.pyx,sha256=AeXcz4_d7lgfmEoVL7QguH8vSKVOK3pZ5RO76KSHktY,22320
15
+ xoscar/core.pyx,sha256=0YvJW2AHgymyfsAlPGvIFw65J5gTKO3PK2p1wl4VlJ0,22388
16
16
  xoscar/debug.py,sha256=hrmxIH6zvTKasQo6PUUgXu5mgEsR0g87Fvpw7CoHipg,5257
17
17
  xoscar/driver.py,sha256=EjZ7HkdSgwtE9pXGiJXXwgWfxaIn10eZyqKpBhelaoc,1414
18
18
  xoscar/entrypoints.py,sha256=BOFOyMIeH3LwRCqonP6-HJGXp1gUdOrHX64KnpAFxjI,1684
@@ -32,7 +32,7 @@ xoscar/backends/allocate_strategy.py,sha256=DzvTlixwzTANURI2mDLHm3vcaugSPDxU6UQZ
32
32
  xoscar/backends/config.py,sha256=7nmvU_19zYR7n-bT8BNasbjntwmobmMiM7wN7O6Lujc,5129
33
33
  xoscar/backends/context.py,sha256=zhOFZk_RPLaJ9a8ZDQBHcV54E6r3-VnLVO-D3pIr1qA,15685
34
34
  xoscar/backends/core.py,sha256=4eMQ5a0-_wYs4OhOWuRIZoBojhMhj7wr6qzo2dqXFSg,7582
35
- xoscar/backends/message.cp39-win_amd64.pyd,sha256=zNA73QFclcS-sFZsm0b2OVfVpTDySlvMDlO5vDfxVC0,263168
35
+ xoscar/backends/message.cp39-win_amd64.pyd,sha256=Xzfg1P9z-ka22DqgXq6tWGKWWXlMycIvsh5cTE9inpU,263168
36
36
  xoscar/backends/message.pyx,sha256=kD_bqaApizHtMzqH0Baw5GH3N7r26NwOGoVfm7KCXWg,18203
37
37
  xoscar/backends/pool.py,sha256=9FBNhiIOu3LJCP6hIkvPKfjvHqgRDQ4Sf1mwrcb9fmk,59720
38
38
  xoscar/backends/router.py,sha256=GJpSV_LhzINHdTp5jtsMHfPNMkNb1KI-WlqGqhwApGU,7953
@@ -56,8 +56,8 @@ xoscar/collective/common.py,sha256=CBikMogIBIqe0U_bhomEPM2fNywthumFea3KuA9hB2U,3
56
56
  xoscar/collective/core.py,sha256=Rx1niJ_6rznLG9varP53oqTH_bZabRzgbuP2V6JPu54,24235
57
57
  xoscar/collective/process_group.py,sha256=kTPbrLMJSGhqbiWvTIiz-X3W0rZWd_CFn_zUIlXbOlM,23286
58
58
  xoscar/collective/utils.py,sha256=p3WEVtXvnVhkuO5mRgQBhBRFr1dKHcDKMjrbMyuiyfg,1219
59
- xoscar/collective/uv.dll,sha256=NcMlxPDCPBrd1dCcsznWBVLK49OluZ_8xJBlAEFPXAI,618496
60
- xoscar/collective/xoscar_pygloo.cp39-win_amd64.pyd,sha256=OyTbonlvzAHs8t67XE9Pm926W4yLCBMH5etOfTG-0VQ,798720
59
+ xoscar/collective/uv.dll,sha256=9yXEQnXa4jR1f_SBXM0QPdvLA2zqRwJ9XRd2IMkqDRg,618496
60
+ xoscar/collective/xoscar_pygloo.cp39-win_amd64.pyd,sha256=mmsZByqe8fdfI1nW6LuymTRS7NOlocb3j3FxJqKNJZ0,798720
61
61
  xoscar/metrics/__init__.py,sha256=RjXuuYw4I2YYgD8UY2Z5yCZk0Z56xMJ1n40O80Dtxf8,726
62
62
  xoscar/metrics/api.py,sha256=dtJ4QrIqQNXhJedeqOPs4TXKgrRGZFFN50xAd9SCfec,9144
63
63
  xoscar/metrics/backends/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS3Ijp1YgyynoUFLeuU,594
@@ -68,7 +68,7 @@ xoscar/metrics/backends/prometheus/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS
68
68
  xoscar/metrics/backends/prometheus/prometheus_metric.py,sha256=65hb8O3tmsEJ7jgOrIwl_suj9SE5Tmqcfjuk0urkLvE,2120
69
69
  xoscar/serialization/__init__.py,sha256=NOAn046vnHEkx--82BKNinV8EpyOfT5hqfRBGnKl56s,866
70
70
  xoscar/serialization/aio.py,sha256=bL31B2lwrEKA5nztRSeSgDyqsbBN6dCMr6rHwNDGAIk,4715
71
- xoscar/serialization/core.cp39-win_amd64.pyd,sha256=kbBOIsxOj54bMrD34QeB3zwdNzMRxThgDaf3HoEf7H0,299520
71
+ xoscar/serialization/core.cp39-win_amd64.pyd,sha256=vxj_VALt2onNfuVmp5CjiGkSLrFR_cBvxPK39yfs8xE,299520
72
72
  xoscar/serialization/core.pxd,sha256=X-47bqBM2Kzw5SkLqICdKD0gU6CpmLsBxC3kfW--wVk,1013
73
73
  xoscar/serialization/core.pyx,sha256=H6YZos-OHDxqFvu1vKvoH3Fhw3HzGn8dI3YPACFL5C0,31085
74
74
  xoscar/serialization/cuda.py,sha256=Fj4Cpr_YmkGceUCo0mQn8fRvmHP_5WcLdRx6epZ3RC0,3869
@@ -76,7 +76,7 @@ xoscar/serialization/exception.py,sha256=t6yZn_Ate04UE1RbabNh7mu739sdtwarjuPXWhA
76
76
  xoscar/serialization/numpy.py,sha256=C6WVx-Sdl2OHBAvVY34DFjAKXlekMbpc2ni6bR8wxYo,3001
77
77
  xoscar/serialization/pyfury.py,sha256=3ucal29Hr7PX9_1SfB2x43FE2xw_C0rLkVv3foL7qwM,1200
78
78
  xoscar/serialization/scipy.py,sha256=9ph-yoRoNiwUZTwQrn35U60VPirWlncXNAg6EXvqMR4,2554
79
- xoscar-0.1.4.dist-info/METADATA,sha256=KCnDiyV5z4m16FpS5Bt_RuyGxboAbE8P_DIQ-tY5xJ4,9438
80
- xoscar-0.1.4.dist-info/WHEEL,sha256=GZFS91_ufm4WrNPBaFVPB9MvOXR6bMZQhPcZRRTN5YM,100
81
- xoscar-0.1.4.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
82
- xoscar-0.1.4.dist-info/RECORD,,
79
+ xoscar-0.2.1.dist-info/METADATA,sha256=EqRTotGIj5L-Ek7P69Ebga1WXy0adVlkaIvhzQ_dzGI,9438
80
+ xoscar-0.2.1.dist-info/WHEEL,sha256=GZFS91_ufm4WrNPBaFVPB9MvOXR6bMZQhPcZRRTN5YM,100
81
+ xoscar-0.2.1.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
82
+ xoscar-0.2.1.dist-info/RECORD,,
File without changes