xoscar 0.3.2__cp39-cp39-macosx_10_9_universal2.whl → 0.4.0__cp39-cp39-macosx_10_9_universal2.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/_utils.cpython-39-darwin.so +0 -0
- xoscar/aio/__init__.py +0 -9
- xoscar/backends/communication/socket.py +49 -10
- xoscar/backends/communication/ucx.py +20 -9
- xoscar/backends/indigen/pool.py +12 -12
- xoscar/backends/message.cpython-39-darwin.so +0 -0
- xoscar/backends/message.pyx +8 -0
- xoscar/backends/pool.py +5 -2
- xoscar/collective/core.py +1 -1
- xoscar/collective/xoscar_pygloo.cpython-39-darwin.so +0 -0
- xoscar/context.cpython-39-darwin.so +0 -0
- xoscar/core.cpython-39-darwin.so +0 -0
- xoscar/serialization/core.cpython-39-darwin.so +0 -0
- xoscar/serialization/core.pyx +1 -11
- xoscar/utils.py +17 -2
- {xoscar-0.3.2.dist-info → xoscar-0.4.0.dist-info}/METADATA +29 -31
- {xoscar-0.3.2.dist-info → xoscar-0.4.0.dist-info}/RECORD +19 -20
- {xoscar-0.3.2.dist-info → xoscar-0.4.0.dist-info}/WHEEL +1 -1
- xoscar/aio/_threads.py +0 -35
- {xoscar-0.3.2.dist-info → xoscar-0.4.0.dist-info}/top_level.txt +0 -0
|
Binary file
|
xoscar/aio/__init__.py
CHANGED
|
@@ -11,15 +11,6 @@
|
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
import asyncio
|
|
16
|
-
import sys
|
|
17
|
-
|
|
18
14
|
from .file import AioFileObject
|
|
19
15
|
from .lru import alru_cache
|
|
20
16
|
from .parallelism import AioEvent
|
|
21
|
-
|
|
22
|
-
if sys.version_info[:2] < (3, 9):
|
|
23
|
-
from ._threads import to_thread
|
|
24
|
-
|
|
25
|
-
asyncio.to_thread = to_thread
|
|
@@ -17,6 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
import asyncio
|
|
19
19
|
import concurrent.futures as futures
|
|
20
|
+
import logging
|
|
20
21
|
import os
|
|
21
22
|
import socket
|
|
22
23
|
import sys
|
|
@@ -30,7 +31,7 @@ from urllib.parse import urlparse
|
|
|
30
31
|
from ..._utils import to_binary
|
|
31
32
|
from ...constants import XOSCAR_UNIX_SOCKET_DIR
|
|
32
33
|
from ...serialization import AioDeserializer, AioSerializer, deserialize
|
|
33
|
-
from ...utils import classproperty, implements
|
|
34
|
+
from ...utils import classproperty, implements, is_py_312, is_v6_ip
|
|
34
35
|
from .base import Channel, ChannelType, Client, Server
|
|
35
36
|
from .core import register_client, register_server
|
|
36
37
|
from .utils import read_buffers, write_buffers
|
|
@@ -38,6 +39,9 @@ from .utils import read_buffers, write_buffers
|
|
|
38
39
|
_is_windows: bool = sys.platform.startswith("win")
|
|
39
40
|
|
|
40
41
|
|
|
42
|
+
logger = logging.getLogger(__name__)
|
|
43
|
+
|
|
44
|
+
|
|
41
45
|
class SocketChannel(Channel):
|
|
42
46
|
__slots__ = "reader", "writer", "_channel_type", "_send_lock", "_recv_lock"
|
|
43
47
|
|
|
@@ -131,11 +135,23 @@ class _BaseSocketServer(Server, metaclass=ABCMeta):
|
|
|
131
135
|
if timeout is None:
|
|
132
136
|
await self._aio_server.serve_forever()
|
|
133
137
|
else:
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
138
|
+
if is_py_312():
|
|
139
|
+
# For python 3.12, there's a bug for `serve_forever`:
|
|
140
|
+
# https://github.com/python/cpython/issues/123720,
|
|
141
|
+
# which is unable to be cancelled.
|
|
142
|
+
# Here is really a simulation of `wait_for`
|
|
143
|
+
task = asyncio.create_task(self._aio_server.serve_forever())
|
|
144
|
+
await asyncio.sleep(timeout)
|
|
145
|
+
if task.done():
|
|
146
|
+
logger.warning(f"`serve_forever` should never be done.")
|
|
147
|
+
else:
|
|
148
|
+
task.cancel()
|
|
149
|
+
else:
|
|
150
|
+
future = asyncio.create_task(self._aio_server.serve_forever())
|
|
151
|
+
try:
|
|
152
|
+
await asyncio.wait_for(future, timeout=timeout)
|
|
153
|
+
except (futures.TimeoutError, asyncio.TimeoutError, TimeoutError):
|
|
154
|
+
future.cancel()
|
|
139
155
|
|
|
140
156
|
@implements(Server.on_connected)
|
|
141
157
|
async def on_connected(self, *args, **kwargs):
|
|
@@ -161,7 +177,10 @@ class _BaseSocketServer(Server, metaclass=ABCMeta):
|
|
|
161
177
|
@implements(Server.stop)
|
|
162
178
|
async def stop(self):
|
|
163
179
|
self._aio_server.close()
|
|
164
|
-
|
|
180
|
+
# Python 3.12: # https://github.com/python/cpython/issues/104344
|
|
181
|
+
# `wait_closed` leads to hang
|
|
182
|
+
if not is_py_312():
|
|
183
|
+
await self._aio_server.wait_closed()
|
|
165
184
|
# close all channels
|
|
166
185
|
await asyncio.gather(
|
|
167
186
|
*(channel.close() for channel in self._channels if not channel.closed)
|
|
@@ -201,17 +220,37 @@ class SocketServer(_BaseSocketServer):
|
|
|
201
220
|
def channel_type(self) -> int:
|
|
202
221
|
return ChannelType.remote
|
|
203
222
|
|
|
223
|
+
@classmethod
|
|
224
|
+
def parse_config(cls, config: dict) -> dict:
|
|
225
|
+
if config is None or not config:
|
|
226
|
+
return dict()
|
|
227
|
+
# we only need the following config
|
|
228
|
+
keys = ["listen_elastic_ip"]
|
|
229
|
+
parsed_config = {key: config[key] for key in keys if key in config}
|
|
230
|
+
|
|
231
|
+
return parsed_config
|
|
232
|
+
|
|
204
233
|
@staticmethod
|
|
205
234
|
@implements(Server.create)
|
|
206
235
|
async def create(config: Dict) -> "Server":
|
|
207
236
|
config = config.copy()
|
|
208
237
|
if "address" in config:
|
|
209
238
|
address = config.pop("address")
|
|
210
|
-
host, port = address.
|
|
239
|
+
host, port = address.rsplit(":", 1)
|
|
211
240
|
port = int(port)
|
|
212
241
|
else:
|
|
213
242
|
host = config.pop("host")
|
|
214
243
|
port = int(config.pop("port"))
|
|
244
|
+
_host = host
|
|
245
|
+
if config.pop("listen_elastic_ip", False):
|
|
246
|
+
# The Actor.address will be announce to client, and is not on our host,
|
|
247
|
+
# cannot actually listen on it,
|
|
248
|
+
# so we have to keep SocketServer.host untouched to make sure Actor.address not changed
|
|
249
|
+
if is_v6_ip(host):
|
|
250
|
+
_host = "::"
|
|
251
|
+
else:
|
|
252
|
+
_host = "0.0.0.0"
|
|
253
|
+
|
|
215
254
|
handle_channel = config.pop("handle_channel")
|
|
216
255
|
if "start_serving" not in config:
|
|
217
256
|
config["start_serving"] = False
|
|
@@ -224,7 +263,7 @@ class SocketServer(_BaseSocketServer):
|
|
|
224
263
|
|
|
225
264
|
port = port if port != 0 else None
|
|
226
265
|
aio_server = await asyncio.start_server(
|
|
227
|
-
handle_connection, host=
|
|
266
|
+
handle_connection, host=_host, port=port, **config
|
|
228
267
|
)
|
|
229
268
|
|
|
230
269
|
# get port of the socket if not specified
|
|
@@ -250,7 +289,7 @@ class SocketClient(Client):
|
|
|
250
289
|
async def connect(
|
|
251
290
|
dest_address: str, local_address: str | None = None, **kwargs
|
|
252
291
|
) -> "Client":
|
|
253
|
-
host, port_str = dest_address.
|
|
292
|
+
host, port_str = dest_address.rsplit(":", 1)
|
|
254
293
|
port = int(port_str)
|
|
255
294
|
(reader, writer) = await asyncio.open_connection(host=host, port=port, **kwargs)
|
|
256
295
|
channel = SocketChannel(
|
|
@@ -28,13 +28,13 @@ import numpy as np
|
|
|
28
28
|
from ...nvutils import get_cuda_context, get_index_and_uuid
|
|
29
29
|
from ...serialization import deserialize
|
|
30
30
|
from ...serialization.aio import BUFFER_SIZES_NAME, AioSerializer, get_header_length
|
|
31
|
-
from ...utils import classproperty, implements, is_cuda_buffer, lazy_import
|
|
31
|
+
from ...utils import classproperty, implements, is_cuda_buffer, is_v6_ip, lazy_import
|
|
32
32
|
from ..message import _MessageBase
|
|
33
33
|
from .base import Channel, ChannelType, Client, Server
|
|
34
34
|
from .core import register_client, register_server
|
|
35
35
|
from .errors import ChannelClosed
|
|
36
36
|
|
|
37
|
-
ucp = lazy_import("
|
|
37
|
+
ucp = lazy_import("ucxx")
|
|
38
38
|
numba_cuda = lazy_import("numba.cuda")
|
|
39
39
|
rmm = lazy_import("rmm")
|
|
40
40
|
|
|
@@ -86,7 +86,7 @@ class UCXInitializer:
|
|
|
86
86
|
tls += ",cuda_copy"
|
|
87
87
|
|
|
88
88
|
if ucx_config.get("infiniband"): # pragma: no cover
|
|
89
|
-
tls = "
|
|
89
|
+
tls = "ib," + tls
|
|
90
90
|
if ucx_config.get("nvlink"): # pragma: no cover
|
|
91
91
|
tls += ",cuda_ipc"
|
|
92
92
|
|
|
@@ -177,7 +177,8 @@ class UCXInitializer:
|
|
|
177
177
|
new_environ.update(envs)
|
|
178
178
|
os.environ = new_environ # type: ignore
|
|
179
179
|
try:
|
|
180
|
-
|
|
180
|
+
# let UCX determine the appropriate transports
|
|
181
|
+
ucp.init()
|
|
181
182
|
finally:
|
|
182
183
|
os.environ = original_environ
|
|
183
184
|
|
|
@@ -313,7 +314,7 @@ class UCXChannel(Channel):
|
|
|
313
314
|
await self.ucp_endpoint.send(buf)
|
|
314
315
|
for buffer in buffers:
|
|
315
316
|
await self.ucp_endpoint.send(buffer)
|
|
316
|
-
except ucp.exceptions.
|
|
317
|
+
except ucp.exceptions.UCXError: # pragma: no cover
|
|
317
318
|
self.abort()
|
|
318
319
|
raise ChannelClosed("While writing, the connection was closed")
|
|
319
320
|
|
|
@@ -401,11 +402,21 @@ class UCXServer(Server):
|
|
|
401
402
|
prefix = f"{UCXServer.scheme}://"
|
|
402
403
|
if address.startswith(prefix):
|
|
403
404
|
address = address[len(prefix) :]
|
|
404
|
-
host, port = address.
|
|
405
|
+
host, port = address.rsplit(":", 1)
|
|
405
406
|
port = int(port)
|
|
406
407
|
else:
|
|
407
408
|
host = config.pop("host")
|
|
408
409
|
port = int(config.pop("port"))
|
|
410
|
+
_host = host
|
|
411
|
+
if config.pop("listen_elastic_ip", False):
|
|
412
|
+
# The Actor.address will be announce to client, and is not on our host,
|
|
413
|
+
# cannot actually listen on it,
|
|
414
|
+
# so we have to keep SocketServer.host untouched to make sure Actor.address not changed
|
|
415
|
+
if is_v6_ip(host):
|
|
416
|
+
_host = "::"
|
|
417
|
+
else:
|
|
418
|
+
_host = "0.0.0.0"
|
|
419
|
+
|
|
409
420
|
handle_channel = config.pop("handle_channel")
|
|
410
421
|
|
|
411
422
|
# init
|
|
@@ -414,7 +425,7 @@ class UCXServer(Server):
|
|
|
414
425
|
async def serve_forever(client_ucp_endpoint: "ucp.Endpoint"): # type: ignore
|
|
415
426
|
try:
|
|
416
427
|
await server.on_connected(
|
|
417
|
-
client_ucp_endpoint, local_address=
|
|
428
|
+
client_ucp_endpoint, local_address="%s:%d" % (_host, port)
|
|
418
429
|
)
|
|
419
430
|
except ChannelClosed: # pragma: no cover
|
|
420
431
|
logger.exception("Connection closed before handshake completed")
|
|
@@ -498,7 +509,7 @@ class UCXClient(Client):
|
|
|
498
509
|
prefix = f"{UCXClient.scheme}://"
|
|
499
510
|
if dest_address.startswith(prefix):
|
|
500
511
|
dest_address = dest_address[len(prefix) :]
|
|
501
|
-
host, port_str = dest_address.
|
|
512
|
+
host, port_str = dest_address.rsplit(":", 1)
|
|
502
513
|
port = int(port_str)
|
|
503
514
|
kwargs = kwargs.copy()
|
|
504
515
|
ucx_config = kwargs.pop("config", dict()).get("ucx", dict())
|
|
@@ -506,7 +517,7 @@ class UCXClient(Client):
|
|
|
506
517
|
|
|
507
518
|
try:
|
|
508
519
|
ucp_endpoint = await ucp.create_endpoint(host, port)
|
|
509
|
-
except ucp.exceptions.
|
|
520
|
+
except ucp.exceptions.UCXError as e: # pragma: no cover
|
|
510
521
|
raise ChannelClosed(
|
|
511
522
|
f"Connection closed before handshake completed, "
|
|
512
523
|
f"local address: {local_address}, dest address: {dest_address}"
|
xoscar/backends/indigen/pool.py
CHANGED
|
@@ -132,7 +132,7 @@ class MainActorPool(MainActorPoolBase):
|
|
|
132
132
|
"""Get external address for every process"""
|
|
133
133
|
assert n_process is not None
|
|
134
134
|
if ":" in address:
|
|
135
|
-
host, port_str = address.
|
|
135
|
+
host, port_str = address.rsplit(":", 1)
|
|
136
136
|
port = int(port_str)
|
|
137
137
|
if ports:
|
|
138
138
|
if len(ports) != n_process:
|
|
@@ -324,6 +324,7 @@ class MainActorPool(MainActorPoolBase):
|
|
|
324
324
|
start_method: str | None = None,
|
|
325
325
|
kwargs: dict | None = None,
|
|
326
326
|
):
|
|
327
|
+
# external_address has port 0, subprocess will bind random port.
|
|
327
328
|
external_address = (
|
|
328
329
|
external_address
|
|
329
330
|
or MainActorPool.get_external_addresses(self.external_address, n_process=1)[
|
|
@@ -393,7 +394,7 @@ class MainActorPool(MainActorPoolBase):
|
|
|
393
394
|
content=self._config,
|
|
394
395
|
)
|
|
395
396
|
await self.handle_control_command(control_message)
|
|
396
|
-
|
|
397
|
+
# The actual port will return in process_status.
|
|
397
398
|
return process_status.external_addresses[0]
|
|
398
399
|
|
|
399
400
|
async def remove_sub_pool(
|
|
@@ -416,22 +417,21 @@ class MainActorPool(MainActorPoolBase):
|
|
|
416
417
|
async def kill_sub_pool(
|
|
417
418
|
self, process: multiprocessing.Process, force: bool = False
|
|
418
419
|
):
|
|
419
|
-
if
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
process.terminate()
|
|
420
|
+
if not force: # pragma: no cover
|
|
421
|
+
# must shutdown gracefully, or subprocess created by model will not exit
|
|
422
|
+
if not _is_windows:
|
|
423
|
+
try:
|
|
424
|
+
os.kill(process.pid, signal.SIGINT) # type: ignore
|
|
425
|
+
except OSError: # pragma: no cover
|
|
426
|
+
pass
|
|
427
|
+
process.terminate() # SIGTERM
|
|
428
428
|
wait_pool = futures.ThreadPoolExecutor(1)
|
|
429
429
|
try:
|
|
430
430
|
loop = asyncio.get_running_loop()
|
|
431
431
|
await loop.run_in_executor(wait_pool, process.join, 3)
|
|
432
432
|
finally:
|
|
433
433
|
wait_pool.shutdown(False)
|
|
434
|
-
process.kill()
|
|
434
|
+
process.kill() # SIGKILL
|
|
435
435
|
await asyncio.to_thread(process.join, 5)
|
|
436
436
|
|
|
437
437
|
async def is_sub_pool_alive(self, process: multiprocessing.Process):
|
|
Binary file
|
xoscar/backends/message.pyx
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
import asyncio
|
|
16
17
|
from enum import Enum
|
|
17
18
|
from types import TracebackType
|
|
18
19
|
from typing import Any, Type
|
|
@@ -21,7 +22,9 @@ from tblib import pickling_support
|
|
|
21
22
|
|
|
22
23
|
from ..core cimport ActorRef, BufferRef
|
|
23
24
|
from ..serialization.core cimport Serializer
|
|
25
|
+
|
|
24
26
|
from ..utils import wrap_exception
|
|
27
|
+
|
|
25
28
|
from .._utils cimport new_random_id
|
|
26
29
|
|
|
27
30
|
# make sure traceback can be pickled
|
|
@@ -245,6 +248,11 @@ cdef class ErrorMessage(_MessageBase):
|
|
|
245
248
|
if issubclass(self.error_type, _AsCauseBase):
|
|
246
249
|
return self.error.with_traceback(self.traceback)
|
|
247
250
|
|
|
251
|
+
# for being compatible with Python 3.12 `asyncio.wait_for`
|
|
252
|
+
# https://github.com/python/cpython/pull/113850
|
|
253
|
+
if isinstance(self.error, asyncio.CancelledError):
|
|
254
|
+
return asyncio.CancelledError(f"[address={self.address}, pid={self.pid}]").with_traceback(self.traceback)
|
|
255
|
+
|
|
248
256
|
return wrap_exception(
|
|
249
257
|
self.error,
|
|
250
258
|
(_AsCauseBase,),
|
xoscar/backends/pool.py
CHANGED
|
@@ -41,7 +41,7 @@ from ..errors import (
|
|
|
41
41
|
ServerClosed,
|
|
42
42
|
)
|
|
43
43
|
from ..metrics import init_metrics
|
|
44
|
-
from ..utils import implements, register_asyncio_task_timeout_detector
|
|
44
|
+
from ..utils import implements, is_zero_ip, register_asyncio_task_timeout_detector
|
|
45
45
|
from .allocate_strategy import AddressSpecified, allocated_type
|
|
46
46
|
from .communication import (
|
|
47
47
|
Channel,
|
|
@@ -164,7 +164,10 @@ class AbstractActorPool(ABC):
|
|
|
164
164
|
):
|
|
165
165
|
# register local pool for local actor lookup.
|
|
166
166
|
# The pool is weakrefed, so we don't need to unregister it.
|
|
167
|
-
|
|
167
|
+
if not is_zero_ip(external_address):
|
|
168
|
+
# Only register_local_pool when we listen on non-zero ip (because all-zero ip is wildcard address),
|
|
169
|
+
# avoid mistaken with another remote service listen on non-zero ip with the same port.
|
|
170
|
+
register_local_pool(external_address, self)
|
|
168
171
|
self.process_index = process_index
|
|
169
172
|
self.label = label
|
|
170
173
|
self.external_address = external_address
|
xoscar/collective/core.py
CHANGED
|
Binary file
|
|
Binary file
|
xoscar/core.cpython-39-darwin.so
CHANGED
|
Binary file
|
|
Binary file
|
xoscar/serialization/core.pyx
CHANGED
|
@@ -55,7 +55,6 @@ from .pyfury import get_fury
|
|
|
55
55
|
|
|
56
56
|
BUFFER_PICKLE_PROTOCOL = max(pickle.DEFAULT_PROTOCOL, 5)
|
|
57
57
|
cdef bint HAS_PICKLE_BUFFER = pickle.HIGHEST_PROTOCOL >= 5
|
|
58
|
-
cdef bint _PANDAS_HAS_MGR = hasattr(pd.Series([0]), "_mgr")
|
|
59
58
|
|
|
60
59
|
cdef TypeDispatcher _serial_dispatcher = TypeDispatcher()
|
|
61
60
|
cdef dict _deserializers = dict()
|
|
@@ -260,16 +259,7 @@ def unpickle_buffers(list buffers):
|
|
|
260
259
|
else:
|
|
261
260
|
result = cloudpickle.loads(buffers[0], buffers=buffers[1:])
|
|
262
261
|
|
|
263
|
-
|
|
264
|
-
# deserializing from high versions may produce mal-functioned pandas objects,
|
|
265
|
-
# thus the patch is needed
|
|
266
|
-
if _PANDAS_HAS_MGR:
|
|
267
|
-
return result
|
|
268
|
-
else: # pragma: no cover
|
|
269
|
-
if hasattr(result, "_mgr") and isinstance(result, (pd.DataFrame, pd.Series)):
|
|
270
|
-
result._data = getattr(result, "_mgr")
|
|
271
|
-
delattr(result, "_mgr")
|
|
272
|
-
return result
|
|
262
|
+
return result
|
|
273
263
|
|
|
274
264
|
|
|
275
265
|
cdef class PickleSerializer(Serializer):
|
xoscar/utils.py
CHANGED
|
@@ -30,6 +30,7 @@ import sys
|
|
|
30
30
|
import time
|
|
31
31
|
import uuid
|
|
32
32
|
from abc import ABC
|
|
33
|
+
from functools import lru_cache
|
|
33
34
|
from types import TracebackType
|
|
34
35
|
from typing import Callable, Type, Union
|
|
35
36
|
|
|
@@ -464,13 +465,18 @@ def is_linux():
|
|
|
464
465
|
return sys.platform.startswith("linux")
|
|
465
466
|
|
|
466
467
|
|
|
468
|
+
@lru_cache
|
|
469
|
+
def is_py_312():
|
|
470
|
+
return sys.version_info[:2] == (3, 12)
|
|
471
|
+
|
|
472
|
+
|
|
467
473
|
def is_v4_zero_ip(ip_port_addr: str) -> bool:
|
|
468
|
-
return ip_port_addr.startswith("0.0.0.0:")
|
|
474
|
+
return ip_port_addr.split("://")[-1].startswith("0.0.0.0:")
|
|
469
475
|
|
|
470
476
|
|
|
471
477
|
def is_v6_zero_ip(ip_port_addr: str) -> bool:
|
|
472
478
|
# tcp6 addr ":::123", ":: means all zero"
|
|
473
|
-
arr = ip_port_addr.split(":")
|
|
479
|
+
arr = ip_port_addr.split("://")[-1].split(":")
|
|
474
480
|
if len(arr) <= 2: # Not tcp6 or udp6
|
|
475
481
|
return False
|
|
476
482
|
for part in arr[0:-1]:
|
|
@@ -480,6 +486,15 @@ def is_v6_zero_ip(ip_port_addr: str) -> bool:
|
|
|
480
486
|
return True
|
|
481
487
|
|
|
482
488
|
|
|
489
|
+
def is_zero_ip(ip_port_addr: str) -> bool:
|
|
490
|
+
return is_v4_zero_ip(ip_port_addr) or is_v6_zero_ip(ip_port_addr)
|
|
491
|
+
|
|
492
|
+
|
|
493
|
+
def is_v6_ip(ip_port_addr: str) -> bool:
|
|
494
|
+
arr = ip_port_addr.split("://", 1)[-1].split(":")
|
|
495
|
+
return len(arr) > 1
|
|
496
|
+
|
|
497
|
+
|
|
483
498
|
def fix_all_zero_ip(remote_addr: str, connect_addr: str) -> str:
|
|
484
499
|
"""
|
|
485
500
|
Use connect_addr to fix ActorRef.address return by remote server.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: xoscar
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Python actor framework for heterogeneous computing.
|
|
5
5
|
Home-page: http://github.com/xorbitsai/xoscar
|
|
6
6
|
Author: Qin Xuye
|
|
@@ -11,48 +11,46 @@ License: Apache License 2.0
|
|
|
11
11
|
Classifier: Operating System :: OS Independent
|
|
12
12
|
Classifier: Programming Language :: Python
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
15
14
|
Classifier: Programming Language :: Python :: 3.9
|
|
16
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
17
16
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
18
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
19
19
|
Classifier: Topic :: Software Development :: Libraries
|
|
20
20
|
Description-Content-Type: text/markdown
|
|
21
|
-
Requires-Dist: numpy
|
|
22
|
-
Requires-Dist: pandas
|
|
23
|
-
Requires-Dist: cloudpickle
|
|
24
|
-
Requires-Dist: psutil
|
|
25
|
-
Requires-Dist: tblib
|
|
21
|
+
Requires-Dist: numpy>=1.14.0
|
|
22
|
+
Requires-Dist: pandas>=1.0.0
|
|
23
|
+
Requires-Dist: cloudpickle>=1.5.0
|
|
24
|
+
Requires-Dist: psutil>=5.9.0
|
|
25
|
+
Requires-Dist: tblib>=1.7.0
|
|
26
26
|
Requires-Dist: packaging
|
|
27
|
-
Requires-Dist:
|
|
28
|
-
Requires-Dist:
|
|
29
|
-
Requires-Dist: scipy
|
|
30
|
-
Requires-Dist: scipy <=1.9.1,>=1.0.0 ; sys_platform == "win32" and python_version < "3.10"
|
|
27
|
+
Requires-Dist: uvloop>=0.14.0; sys_platform != "win32"
|
|
28
|
+
Requires-Dist: scipy>=1.0.0; sys_platform != "win32" or python_version >= "3.10"
|
|
29
|
+
Requires-Dist: scipy<=1.9.1,>=1.0.0; sys_platform == "win32" and python_version < "3.10"
|
|
31
30
|
Provides-Extra: dev
|
|
32
|
-
Requires-Dist: cython
|
|
33
|
-
Requires-Dist: pytest
|
|
34
|
-
Requires-Dist: pytest-cov
|
|
35
|
-
Requires-Dist: pytest-timeout
|
|
36
|
-
Requires-Dist: pytest-forked
|
|
37
|
-
Requires-Dist: pytest-asyncio
|
|
38
|
-
Requires-Dist: ipython
|
|
39
|
-
Requires-Dist: sphinx
|
|
40
|
-
Requires-Dist: pydata-sphinx-theme
|
|
41
|
-
Requires-Dist: sphinx-intl
|
|
42
|
-
Requires-Dist: flake8
|
|
43
|
-
Requires-Dist: black
|
|
44
|
-
Requires-Dist: mock >=4.0.0 ; (python_version < "3.8") and extra == 'dev'
|
|
31
|
+
Requires-Dist: cython>=0.29; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest>=3.5.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=2.5.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-timeout>=1.2.0; extra == "dev"
|
|
35
|
+
Requires-Dist: pytest-forked>=1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-asyncio>=0.14.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ipython>=6.5.0; extra == "dev"
|
|
38
|
+
Requires-Dist: sphinx; extra == "dev"
|
|
39
|
+
Requires-Dist: pydata-sphinx-theme>=0.3.0; extra == "dev"
|
|
40
|
+
Requires-Dist: sphinx-intl>=0.9.9; extra == "dev"
|
|
41
|
+
Requires-Dist: flake8>=3.8.0; extra == "dev"
|
|
42
|
+
Requires-Dist: black; extra == "dev"
|
|
45
43
|
Provides-Extra: doc
|
|
46
|
-
Requires-Dist: ipython
|
|
47
|
-
Requires-Dist: sphinx
|
|
48
|
-
Requires-Dist: pydata-sphinx-theme
|
|
49
|
-
Requires-Dist: sphinx-intl
|
|
44
|
+
Requires-Dist: ipython>=6.5.0; extra == "doc"
|
|
45
|
+
Requires-Dist: sphinx; extra == "doc"
|
|
46
|
+
Requires-Dist: pydata-sphinx-theme>=0.3.0; extra == "doc"
|
|
47
|
+
Requires-Dist: sphinx-intl>=0.9.9; extra == "doc"
|
|
50
48
|
Provides-Extra: extra
|
|
51
|
-
Requires-Dist: pyarrow
|
|
49
|
+
Requires-Dist: pyarrow>=5.0.0; extra == "extra"
|
|
52
50
|
Provides-Extra: kubernetes
|
|
53
|
-
Requires-Dist: kubernetes
|
|
51
|
+
Requires-Dist: kubernetes>=10.0.0; extra == "kubernetes"
|
|
54
52
|
Provides-Extra: ray
|
|
55
|
-
Requires-Dist: xoscar-ray
|
|
53
|
+
Requires-Dist: xoscar-ray>=0.0.1; extra == "ray"
|
|
56
54
|
|
|
57
55
|
<div align="center">
|
|
58
56
|
<img width="77%" alt="" src="https://raw.githubusercontent.com/xprobe-inc/xoscar/main/doc/source/_static/Xoscar.svg"><br>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
xoscar-0.
|
|
2
|
-
xoscar-0.
|
|
3
|
-
xoscar-0.
|
|
4
|
-
xoscar-0.
|
|
1
|
+
xoscar-0.4.0.dist-info/RECORD,,
|
|
2
|
+
xoscar-0.4.0.dist-info/WHEEL,sha256=UlAYE9MX3bpLspwUrwA_Bk4EdfKlHrjGrLRU16v06yE,113
|
|
3
|
+
xoscar-0.4.0.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
|
|
4
|
+
xoscar-0.4.0.dist-info/METADATA,sha256=xfdfy3u6wkQ-IEUMahgHm_ZjZWpKu-VQkoBojz7E8eU,9042
|
|
5
5
|
xoscar/_utils.pyx,sha256=UR1FtYXAYKIdEWR9HulEpMbSOrkQWi6xGz63d4IQmG0,7059
|
|
6
6
|
xoscar/backend.py,sha256=is436OPkZfSpQXaoqTRVta5eoye_pp45RFgCstAk2hU,1850
|
|
7
7
|
xoscar/core.pxd,sha256=4lBq8J0kjcXcsGuvN7Kv4xcL5liHwTTFWlqyK7XAEnw,1280
|
|
@@ -12,18 +12,18 @@ xoscar/nvutils.py,sha256=qmW4mKLU0WB2yCs198ccQOgLL02zB7Fsa-AotO3NOmg,20412
|
|
|
12
12
|
xoscar/constants.py,sha256=Yn59lRIOvE1VFwyuZB5G2-gxYIyhIZ1rVovbdFAR2NM,759
|
|
13
13
|
xoscar/__init__.py,sha256=0zX8kKaio3ZIrlzB79WybcravMJw1OxPWjDspTgJFyQ,1608
|
|
14
14
|
xoscar/api.py,sha256=3hztPoOxg8A_mlhWyWgVP7FMXG0PATA1TP4Rbaj7A-g,13327
|
|
15
|
-
xoscar/core.cpython-39-darwin.so,sha256=
|
|
16
|
-
xoscar/utils.py,sha256=
|
|
15
|
+
xoscar/core.cpython-39-darwin.so,sha256=OQ7DCS6ZrimGZ7PZgWiUpLgtZju3PQfT8R15r3us35o,899936
|
|
16
|
+
xoscar/utils.py,sha256=vAgTMpEyzBNKT4u05-ii9wg_5-7Iq5c8TthyMpz6M_M,16451
|
|
17
17
|
xoscar/debug.py,sha256=9Z8SgE2WaKYQcyDo-5-DxEJQ533v7kWjrvCd28pSx3E,5069
|
|
18
18
|
xoscar/libcpp.pxd,sha256=DJqBxLFOKL4iRr9Kale5UH3rbvPRD1x5bTSOPHFpz9I,1147
|
|
19
19
|
xoscar/context.pyx,sha256=8CdgPnWcE9eOp3N600WgDQ03MCi8P73eUOGcfV7Zksg,10942
|
|
20
20
|
xoscar/errors.py,sha256=wBlQOKsXf0Fc4skN39tDie0YZT-VIAuLNRgoDl2pZcA,1241
|
|
21
|
-
xoscar/_utils.cpython-39-darwin.so,sha256=
|
|
21
|
+
xoscar/_utils.cpython-39-darwin.so,sha256=gLXT7DkGUUe1y822TvIMXJUKXNzAaGxzo3N2k4vWxHc,348016
|
|
22
22
|
xoscar/core.pyx,sha256=Aqc2i8Fetsd5wRAPF4kL0ddnBZn3E2HRNCvup79BbQc,21730
|
|
23
23
|
xoscar/driver.py,sha256=498fowtJr6b3FE8FIOA_Tc1Vwx88nfZw7p0FxrML0h4,1372
|
|
24
24
|
xoscar/profiling.py,sha256=BC5OF0HzSaXv8V7w-y-B8r5gV5DgxHFoTEIF6jCMioQ,8015
|
|
25
25
|
xoscar/_utils.pxd,sha256=5KYAL3jfPdejsHnrGGT2s--ZUX5SXznQWpHVSno429k,1157
|
|
26
|
-
xoscar/context.cpython-39-darwin.so,sha256=
|
|
26
|
+
xoscar/context.cpython-39-darwin.so,sha256=djhAc8Cch_-kbB4KIgK1rOu_6zW2uwFyEmQBsAAqXT4,439376
|
|
27
27
|
xoscar/metrics/__init__.py,sha256=9Badi7rxYikGm2dQiNCrj9GgMRBxwuR3JaEKcFZmfak,705
|
|
28
28
|
xoscar/metrics/api.py,sha256=BBlMIFvVAGVfrtpeJ1YlH9Tqhy9OzGavwvGyeHcQ0Tk,8856
|
|
29
29
|
xoscar/metrics/backends/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4BRnvKta_7VLQAL1ms,581
|
|
@@ -32,9 +32,9 @@ xoscar/metrics/backends/prometheus/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4
|
|
|
32
32
|
xoscar/metrics/backends/prometheus/prometheus_metric.py,sha256=MxoMvVrg0pOkKpkjJ0PcAuEaaEJR2FZljmPrLjQ1-oc,2050
|
|
33
33
|
xoscar/metrics/backends/console/console_metric.py,sha256=y5CCtH33j3AqI5_Uhwi4mgOcAhyhb4cWv_YvR6fxcbQ,2082
|
|
34
34
|
xoscar/metrics/backends/console/__init__.py,sha256=h_JgzSqV5lP6vQ6XX_17kE4IY4BRnvKta_7VLQAL1ms,581
|
|
35
|
-
xoscar/collective/xoscar_pygloo.cpython-39-darwin.so,sha256=
|
|
35
|
+
xoscar/collective/xoscar_pygloo.cpython-39-darwin.so,sha256=0SLT4a3wp83orSTXckMWtigaZyX5an-UZz-uQmZ41oI,2314736
|
|
36
36
|
xoscar/collective/__init__.py,sha256=XsClIkO_3Jd8GDifYuAbZCmJLAo9ZqGvnjUn9iuogmU,774
|
|
37
|
-
xoscar/collective/core.py,sha256=
|
|
37
|
+
xoscar/collective/core.py,sha256=NVR-7Iaq3aDPCN6fgXcq9Ew6uFEszRwxYqmUG9FLcws,23502
|
|
38
38
|
xoscar/collective/common.py,sha256=INAnISbfnRicbbbDHTqbSr9ITb89ZphH5BUkSpEdXXU,3561
|
|
39
39
|
xoscar/collective/utils.py,sha256=3S4qF4JEnAUD3RiWVBUj-ZptL83CBSwGYyVZyIasAsE,1178
|
|
40
40
|
xoscar/collective/process_group.py,sha256=zy7LcIFnEcmrcxuECI89v0bQlUbSqQMkVyBw468WBnk,22599
|
|
@@ -43,37 +43,36 @@ xoscar/serialization/pyfury.py,sha256=sifOnVMYoS82PzZEkzkfxesmMHei23k5UAUUKUyoOY
|
|
|
43
43
|
xoscar/serialization/core.pxd,sha256=k4RoJgX5E5LGs4jdCQ7vvcn26MabXbrWoWhkO49X6YI,985
|
|
44
44
|
xoscar/serialization/__init__.py,sha256=5Y_C3cYbQJIZ09LRjeCf-jrkLma7mfN8I5bznHrdsbg,846
|
|
45
45
|
xoscar/serialization/numpy.py,sha256=5Kem87CvpJmzUMp3QHk4WeHU30FoQWTJJP2SwIcaQG0,2919
|
|
46
|
-
xoscar/serialization/core.cpython-39-darwin.so,sha256=
|
|
46
|
+
xoscar/serialization/core.cpython-39-darwin.so,sha256=CYTK1VmlqXOCGv96EwenG5GwKOmCDsXyj7gFK6UQgVc,804816
|
|
47
47
|
xoscar/serialization/cuda.py,sha256=iFUEnN4SiquBIhyieyOrfw3TnKnW-tU_vYgqOxO_DrA,3758
|
|
48
48
|
xoscar/serialization/scipy.py,sha256=yOEi0NB8cqQ6e2UnCZ1w006RsB7T725tIL-DM_hNcsU,2482
|
|
49
49
|
xoscar/serialization/aio.py,sha256=S9e3rHMBwqqKmJtDz7KzYAqWc8w9bttA0Dj83IBfEU0,4577
|
|
50
|
-
xoscar/serialization/core.pyx,sha256=
|
|
51
|
-
xoscar/backends/message.cpython-39-darwin.so,sha256=
|
|
50
|
+
xoscar/serialization/core.pyx,sha256=bjR-zXGm9qersk7kYPzpjpMIxDl_Auur4BCubRfKmfA,29626
|
|
51
|
+
xoscar/backends/message.cpython-39-darwin.so,sha256=U9BKs-KB87j4FAE-vW5u-6rJJCYSylEynv7TgEcIBUY,771552
|
|
52
52
|
xoscar/backends/config.py,sha256=EG26f0GwX_f4dAhwTW77RBjiK9h8R_3JrD-rBF1bAq8,4984
|
|
53
53
|
xoscar/backends/allocate_strategy.py,sha256=tC1Nbq2tJohahUwd-zoRYHEDX65wyuX8tmeY45uWj_w,4845
|
|
54
54
|
xoscar/backends/__init__.py,sha256=VHEBQcUWM5bj027W8EUf9PiJUAP7JoMrRw3Tsvy5ySw,643
|
|
55
55
|
xoscar/backends/core.py,sha256=aHb3mMZ9vJe6pxg0P8kSOKvjXF1IaqgOgyhKVhHpNLM,7432
|
|
56
56
|
xoscar/backends/context.py,sha256=Vr_PibRxYCDQ_gYK7r-BOlw9TXw8VQbFsVTH7K7mHPk,15470
|
|
57
57
|
xoscar/backends/router.py,sha256=mhSvM5KVfV882jricVcpyxAqHEvhS4zL6ivczC6fOTE,7746
|
|
58
|
-
xoscar/backends/message.pyx,sha256=
|
|
59
|
-
xoscar/backends/pool.py,sha256=
|
|
58
|
+
xoscar/backends/message.pyx,sha256=uyzilPc_7SqNwGUL4U-Zbfqku8bfZyRW_Lt_S3I_LEU,17930
|
|
59
|
+
xoscar/backends/pool.py,sha256=itI9Ho6XjHjBY49-WPBu2absEUFOSCpQhgQ6OnUIm-4,59421
|
|
60
60
|
xoscar/backends/indigen/backend.py,sha256=znl_fZzWGEtLH8hZ9j9Kkf0fva25jEem2_KO7I1RVvc,1612
|
|
61
61
|
xoscar/backends/indigen/__init__.py,sha256=tKHP5ClzedBRBpZsLRVErR3EUNbbDm4CY4u0rCFJr44,685
|
|
62
62
|
xoscar/backends/indigen/driver.py,sha256=VGzkacYKykegW5qhCuhx01gdgBZEKJjNIyfNCnA6Nm8,952
|
|
63
|
-
xoscar/backends/indigen/pool.py,sha256=
|
|
63
|
+
xoscar/backends/indigen/pool.py,sha256=mWYkOP4VVoUsXFgfpwruPuWblF6Waan5vxit8B-9_oQ,16852
|
|
64
64
|
xoscar/backends/test/backend.py,sha256=nv9WFhH5Bbq4Q1HB9yfpciZBaeHT4IQAtzugBWESrUY,1263
|
|
65
65
|
xoscar/backends/test/__init__.py,sha256=j2ZfD6prD9WjUxRUDC7Eq5Z7N7TkL6fFr59oNyc_vY4,682
|
|
66
66
|
xoscar/backends/test/pool.py,sha256=TW4X6J-92Pti66103poQBNDBznX6CBD3RLOc_zixjTo,7257
|
|
67
|
-
xoscar/backends/communication/ucx.py,sha256=
|
|
67
|
+
xoscar/backends/communication/ucx.py,sha256=7GAKIzlbxy-NpaDE9VLPde90tKxeU8lVZH8c_3ByuZ0,19703
|
|
68
68
|
xoscar/backends/communication/__init__.py,sha256=tB05BlK63iWQnfJgRzKt4mFKRtmWUki5hUGSZQwAotc,1050
|
|
69
69
|
xoscar/backends/communication/core.py,sha256=sJeE3foRIqVPXldzYpFKHDSsabfAIFBU4JuXY4OyklY,2130
|
|
70
70
|
xoscar/backends/communication/utils.py,sha256=AmovE-hmWLXNCPwHafYuaRjOk8m42BUyT3XBqfXQRVI,3664
|
|
71
71
|
xoscar/backends/communication/errors.py,sha256=V3CdBe2xX9Rwv32f2dH2Msc84yaUhlyerZ42-739o1Q,723
|
|
72
|
-
xoscar/backends/communication/socket.py,sha256=
|
|
72
|
+
xoscar/backends/communication/socket.py,sha256=DXeYt8mFPnN5Cdg3BGFsmnJc0Ck4_OONveJwAGq44OM,13389
|
|
73
73
|
xoscar/backends/communication/dummy.py,sha256=gaKPNiN4x2aGZV3IGaaa8eaweBVjRh8B19jU1B5t2yw,7798
|
|
74
74
|
xoscar/backends/communication/base.py,sha256=0P4Tr35GSWpRp394e9jVWUUoKKa-gIk177eYPw1BnSU,7421
|
|
75
|
-
xoscar/aio/__init__.py,sha256=
|
|
76
|
-
xoscar/aio/_threads.py,sha256=WE9_NZY3K9n5bAzXRbj1Bc4dxS-1m1erMfZsUu-ULU4,1313
|
|
75
|
+
xoscar/aio/__init__.py,sha256=kViDKR_kJe59VQViHITKEfBcIgN4ZJblUyd8zl0E3ZI,675
|
|
77
76
|
xoscar/aio/file.py,sha256=PBtkLp-Q7XtYl-zk00s18TtgIrkNr60J3Itf66ctO1o,1486
|
|
78
77
|
xoscar/aio/lru.py,sha256=rpXCqSLtPV5xnWtd6uDwQQFGgIPEgvmWEQDkPNUx9cM,6311
|
|
79
78
|
xoscar/aio/parallelism.py,sha256=VSsjk8wP-Bw7tLeUsTyLVNgp91thjxEfE3pCrw_vF5Q,1293
|
xoscar/aio/_threads.py
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# Copyright 2022-2023 XProbe Inc.
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
14
|
-
|
|
15
|
-
import contextvars
|
|
16
|
-
import functools
|
|
17
|
-
from asyncio import events
|
|
18
|
-
|
|
19
|
-
__all__ = ("to_thread",)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
async def to_thread(func, *args, **kwargs):
|
|
23
|
-
"""Asynchronously run function *func* in a separate thread.
|
|
24
|
-
|
|
25
|
-
Any *args and **kwargs supplied for this function are directly passed
|
|
26
|
-
to *func*. Also, the current :class:`contextvars.Context` is propagated,
|
|
27
|
-
allowing context variables from the main thread to be accessed in the
|
|
28
|
-
separate thread.
|
|
29
|
-
|
|
30
|
-
Return a coroutine that can be awaited to get the eventual result of *func*.
|
|
31
|
-
"""
|
|
32
|
-
loop = events.get_running_loop()
|
|
33
|
-
ctx = contextvars.copy_context()
|
|
34
|
-
func_call = functools.partial(ctx.run, func, *args, **kwargs)
|
|
35
|
-
return await loop.run_in_executor(None, func_call)
|
|
File without changes
|