xoscar 0.7.10__cp311-cp311-win_amd64.whl → 0.7.12__cp311-cp311-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.

Binary file
Binary file
xoscar/collective/uv.dll CHANGED
Binary file
Binary file
Binary file
@@ -40,25 +40,27 @@ dtype_map = {
40
40
  class MLXSerislizer(Serializer):
41
41
  @buffered
42
42
  def serial(self, obj: "mx.array", context: dict): # type: ignore
43
- mv = memoryview(obj)
44
- header = dict(shape=obj.shape, format=mv.format)
45
- # If the memoryview is a multi-dimension view, then there could
46
- # trigger a bug of asyncio write: https://github.com/python/cpython/issues/135862
47
- if mv.ndim > 1 or not mv.c_contiguous:
43
+ ravel_obj = obj.reshape(-1).view(mx.uint8)
44
+ mv = memoryview(ravel_obj)
45
+ header = dict(
46
+ shape=obj.shape, format=mv.format, dtype=str(obj.dtype).rsplit(".", 1)[-1]
47
+ )
48
+ if not mv.c_contiguous:
49
+ # NOTE: we only consider c contiguous here,
50
+ # MLX has no way to create f contiguous arrays.
48
51
  mv = memoryview(bytes(mv))
49
52
  return (header,), [mv], True
50
53
 
51
54
  def deserial(self, serialized: tuple, context: dict, subs: List[Any]):
52
55
  header = serialized[0]
53
- shape, format = header["shape"], header["format"]
56
+ shape, format, dtype = header["shape"], header["format"], header["dtype"]
54
57
  mv = memoryview(subs[0])
55
58
  if mv.format != format:
56
59
  dtype = dtype_map.get(format, np.uint8)
57
60
  np_arr = np.frombuffer(mv, dtype=dtype).reshape(shape) # parse
58
61
  mv = memoryview(np_arr) # recreate memoryview
59
- elif mv.shape != shape:
60
- mv = mv.cast(format, shape) # cast directly
61
- return mx.array(mv)
62
+ ravel_array = mx.array(mv)
63
+ return ravel_array.view(getattr(mx, dtype)).reshape(shape)
62
64
 
63
65
 
64
66
  if mx is not None:
xoscar/virtualenv/uv.py CHANGED
@@ -16,17 +16,24 @@ from __future__ import annotations
16
16
 
17
17
  import logging
18
18
  import os
19
+ import re
19
20
  import shutil
20
21
  import subprocess
21
22
  import sys
22
23
  import sysconfig
24
+ import tempfile
25
+ from importlib.metadata import distributions
23
26
  from pathlib import Path
24
27
  from typing import Optional
25
28
 
29
+ from packaging.requirements import Requirement
30
+ from packaging.version import Version
31
+
26
32
  from .core import VirtualEnvManager
27
33
  from .utils import run_subprocess_with_logger
28
34
 
29
35
  UV_PATH = os.getenv("XOSCAR_UV_PATH")
36
+ SKIP_INSTALLED = bool(int(os.getenv("XOSCAR_VIRTUAL_ENV_SKIP_INSTALLED", "0")))
30
37
  logger = logging.getLogger(__name__)
31
38
 
32
39
 
@@ -46,7 +53,8 @@ class UVVirtualEnvManager(VirtualEnvManager):
46
53
  return True
47
54
  return shutil.which("uv") is not None
48
55
 
49
- def create_env(self, python_path: Path | None = None) -> None:
56
+ @staticmethod
57
+ def _get_uv_path() -> str:
50
58
  if (uv_path := UV_PATH) is None:
51
59
  try:
52
60
  from uv import find_uv_bin
@@ -55,6 +63,10 @@ class UVVirtualEnvManager(VirtualEnvManager):
55
63
  except (ImportError, FileNotFoundError):
56
64
  logger.warning("Fail to find uv bin, use system one")
57
65
  uv_path = "uv"
66
+ return uv_path
67
+
68
+ def create_env(self, python_path: Path | None = None) -> None:
69
+ uv_path = self._get_uv_path()
58
70
  cmd = [uv_path, "venv", str(self.env_path), "--system-site-packages"]
59
71
  if python_path:
60
72
  cmd += ["--python", str(python_path)]
@@ -67,6 +79,112 @@ class UVVirtualEnvManager(VirtualEnvManager):
67
79
  logger.info("Creating virtualenv via command: %s", cmd)
68
80
  subprocess.run(cmd, check=True)
69
81
 
82
+ def _resolve_install_plan(
83
+ self, specs: list[str], pinned: dict[str, str]
84
+ ) -> list[str]:
85
+ """
86
+ Run uv --dry-run with pinned constraints and return
87
+ a list like ['package==version', ...].
88
+ """
89
+ with tempfile.NamedTemporaryFile("w+", delete=True) as f:
90
+ for name, ver in pinned.items():
91
+ f.write(f"{name}=={ver}\n")
92
+ f.flush() # make sure content is on disk
93
+
94
+ cmd = [
95
+ self._get_uv_path(),
96
+ "pip",
97
+ "install",
98
+ "-p",
99
+ str(self.env_path),
100
+ "--dry-run",
101
+ "--constraint",
102
+ f.name,
103
+ *specs,
104
+ ]
105
+ result = subprocess.run(cmd, check=True, text=True, capture_output=True)
106
+
107
+ # the temp file is automatically deleted here
108
+ deps = [
109
+ f"{m.group(1)}=={m.group(2)}"
110
+ for line in result.stderr.splitlines()
111
+ if (m := re.match(r"^\+ (\S+)==(\S+)$", line.strip()))
112
+ ]
113
+ return deps
114
+
115
+ @staticmethod
116
+ def _split_specs(
117
+ specs: list[str], installed: dict[str, str]
118
+ ) -> tuple[list[str], dict[str, str]]:
119
+ """
120
+ Split the given requirement specs into:
121
+ - to_resolve: specs that need to be passed to the resolver (unsatisfied ones)
122
+ - pinned: already satisfied specs, used for constraint to lock their versions
123
+ """
124
+ to_resolve: list[str] = []
125
+ pinned: dict[str, str] = {}
126
+
127
+ for spec_str in specs:
128
+ req = Requirement(spec_str)
129
+ name = req.name.lower()
130
+ cur_ver = installed.get(name)
131
+
132
+ if cur_ver is None:
133
+ # Package not installed, needs resolution
134
+ to_resolve.append(spec_str)
135
+ continue
136
+
137
+ if not req.specifier:
138
+ # No version constraint, already satisfied
139
+ pinned[name] = cur_ver
140
+ continue
141
+
142
+ try:
143
+ if Version(cur_ver) in req.specifier:
144
+ # Version satisfies the specifier, pin it
145
+ pinned[name] = cur_ver
146
+ else:
147
+ # Version does not satisfy, needs resolution
148
+ to_resolve.append(spec_str)
149
+ except Exception:
150
+ # Parsing error, be conservative and resolve it
151
+ to_resolve.append(spec_str)
152
+
153
+ return to_resolve, pinned
154
+
155
+ def _filter_packages_not_installed(self, packages: list[str]) -> list[str]:
156
+ """
157
+ Filter out packages that are already installed with the same version.
158
+ """
159
+
160
+ # all the installed packages in system site packages
161
+ installed = {
162
+ dist.metadata["Name"].lower(): dist.version
163
+ for dist in distributions()
164
+ if dist.metadata and "Name" in dist.metadata
165
+ }
166
+
167
+ # exclude those packages that satisfied in system site packages
168
+ to_resolve, pinned = self._split_specs(packages, installed)
169
+ if not to_resolve:
170
+ logger.debug("All requirement specifiers satisfied by system packages.")
171
+ return []
172
+
173
+ resolved = self._resolve_install_plan(to_resolve, pinned)
174
+ logger.debug(f"Resolved install list: {resolved}")
175
+ if not resolved:
176
+ # no packages to install
177
+ return []
178
+
179
+ final = []
180
+ for item in resolved:
181
+ name, version = item.split("==")
182
+ key = name.lower()
183
+ if key not in installed or installed[key] != version:
184
+ final.append(item)
185
+ logger.debug(f"Filtered install list: {final}")
186
+ return final
187
+
70
188
  def install_packages(self, packages: list[str], **kwargs):
71
189
  """
72
190
  Install packages into the virtual environment using uv.
@@ -75,22 +193,36 @@ class UVVirtualEnvManager(VirtualEnvManager):
75
193
  if not packages:
76
194
  return
77
195
 
78
- # extend the ability of pip
79
- # maybe replace #system_torch# to the real version
80
196
  packages = self.process_packages(packages)
81
197
  log = kwargs.pop("log", False)
198
+ skip_installed = kwargs.pop("skip_installed", SKIP_INSTALLED)
199
+ uv_path = self._get_uv_path()
200
+
201
+ if skip_installed:
202
+ packages = self._filter_packages_not_installed(packages)
203
+ if not packages:
204
+ logger.info("All required packages are already installed.")
205
+ return
206
+
207
+ cmd = [
208
+ uv_path,
209
+ "pip",
210
+ "install",
211
+ "-p",
212
+ str(self.env_path),
213
+ "--color=always",
214
+ "--no-deps",
215
+ ] + packages
216
+ else:
217
+ cmd = [
218
+ uv_path,
219
+ "pip",
220
+ "install",
221
+ "-p",
222
+ str(self.env_path),
223
+ "--color=always",
224
+ ] + packages
82
225
 
83
- uv_path = UV_PATH or "uv"
84
- cmd = [
85
- uv_path,
86
- "pip",
87
- "install",
88
- "-p",
89
- str(self.env_path),
90
- "--color=always",
91
- ] + packages
92
-
93
- # Handle known pip-related kwargs
94
226
  if "index_url" in kwargs and kwargs["index_url"]:
95
227
  cmd += ["-i", kwargs["index_url"]]
96
228
  param_and_option = [
@@ -100,12 +232,13 @@ class UVVirtualEnvManager(VirtualEnvManager):
100
232
  ]
101
233
  for param, option in param_and_option:
102
234
  if param in kwargs and kwargs[param]:
103
- param_value = kwargs[param]
104
- if isinstance(param_value, list):
105
- for it in param_value:
106
- cmd += [option, it]
107
- else:
108
- cmd += [option, param_value]
235
+ val = kwargs[param]
236
+ cmd += (
237
+ [option, val]
238
+ if isinstance(val, str)
239
+ else [opt for v in val for opt in (option, v)]
240
+ )
241
+
109
242
  if kwargs.get("no_build_isolation", False):
110
243
  cmd += ["--no-build-isolation"]
111
244
 
@@ -118,8 +251,7 @@ class UVVirtualEnvManager(VirtualEnvManager):
118
251
  self._install_process = process
119
252
  returncode = process.returncode
120
253
 
121
- self._install_process = None # install finished, clear reference
122
-
254
+ self._install_process = None
123
255
  if returncode != 0:
124
256
  raise subprocess.CalledProcessError(returncode, cmd)
125
257
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: xoscar
3
- Version: 0.7.10
3
+ Version: 0.7.12
4
4
  Summary: Python actor framework for heterogeneous computing.
5
5
  Home-page: http://github.com/xorbitsai/xoscar
6
6
  Author: Qin Xuye
@@ -1,5 +1,5 @@
1
1
  xoscar/__init__.py,sha256=lzCXUmkuIjcjkiNQFekysdJR_ZhlbjcfR5ka1bZZNQg,1683
2
- xoscar/_utils.cp311-win_amd64.pyd,sha256=TmU2T28gs-dget7l9xDDJzbcY6MCPmPcVEmQzsfnvwI,106496
2
+ xoscar/_utils.cp311-win_amd64.pyd,sha256=ok1BH1foT600vE75P1ejd0GDHWHkw6SohBpkXAd1__0,111616
3
3
  xoscar/_utils.pxd,sha256=rlNbTg5lhXA-jCOLksqF4jhUlNn0xw2jx1HxdLa34pc,1193
4
4
  xoscar/_utils.pyx,sha256=TWScgqmJGYzjbWBOShBLkq07ldfYEQ5fw6V4OytX_IA,7626
5
5
  xoscar/_version.py,sha256=bsfCVAo_o9LkiP3AjPsP4SRRqhjuS0t4D1WGJPzbdls,24412
@@ -7,10 +7,10 @@ xoscar/api.py,sha256=QQDHn-_FiDExmOxEk8BUnq4Qrx13VX3shSlEEqPQJo0,15175
7
7
  xoscar/backend.py,sha256=8G5JwjoOT6Q2slb11eXNApxgcmvNQUCdQzkoIMDwLcQ,1917
8
8
  xoscar/batch.py,sha256=Jk5BSpvMFAV9DrRy0a9tgPvIo_dt8cbJReZBL0cnOPc,8128
9
9
  xoscar/constants.py,sha256=GJ1KEOxwnqksc9K_GH42TSWpQECeC6ti3KJmE3PUcTw,810
10
- xoscar/context.cp311-win_amd64.pyd,sha256=_D5UEnWLE9aZxlwDsOeAxkBDP2a16xN4JkWa_1RO5yY,152064
10
+ xoscar/context.cp311-win_amd64.pyd,sha256=Jat65SDObGpzyii9jYFBQuJiOvMRCViQW1CLQ8H8cPg,161792
11
11
  xoscar/context.pxd,sha256=6n6IAbmArSRq8EjcsbS6npW8xP1jI0qOoS1fF0oyj-o,746
12
12
  xoscar/context.pyx,sha256=FOJVerGOvxe2USryXEQA0rpaFX_ScxISH6QWKUcahY8,11310
13
- xoscar/core.cp311-win_amd64.pyd,sha256=4BmvDAolm5U3kxvdPyCzQw8YrM54Ru9EnlAYZcR2nmE,303104
13
+ xoscar/core.cp311-win_amd64.pyd,sha256=SdkCFqBYK9VR9pR2FbIZvLJ65QmF9aB7cgqZ7e9Si9M,321024
14
14
  xoscar/core.pxd,sha256=9IZP7dYGfnF1I-obIls8R8b6forxDOPbiM3v5nVslLk,1368
15
15
  xoscar/core.pyx,sha256=U6jCZN74MQHi7HkQRaVGm_w5q-FMsw0nnE3aU6533_Q,22756
16
16
  xoscar/debug.py,sha256=hrmxIH6zvTKasQo6PUUgXu5mgEsR0g87Fvpw7CoHipg,5257
@@ -30,7 +30,7 @@ xoscar/backends/allocate_strategy.py,sha256=DzvTlixwzTANURI2mDLHm3vcaugSPDxU6UQZ
30
30
  xoscar/backends/config.py,sha256=86j0g_Xrl8ENPzBWi296yWg9QEcljvdKK-yJbfYTvQ0,5532
31
31
  xoscar/backends/context.py,sha256=qWwksx8JxYcKR-LQA3PvXh4ReuuTTEyDaLbjpxGXcTA,16766
32
32
  xoscar/backends/core.py,sha256=fbekAxys_t1Dv7if-1R6uVvC_yAxNkXLeQ1V1ZSAfC0,11161
33
- xoscar/backends/message.cp311-win_amd64.pyd,sha256=n_VYHMjY_uZ7mOwb8ECdTHEXTS8eCAFNwsvan_Qfgys,247296
33
+ xoscar/backends/message.cp311-win_amd64.pyd,sha256=CyLLzIjiZ8Ego1tk1EAZZGe4qbCtXRprQOSw9TeOMLY,244224
34
34
  xoscar/backends/message.pyx,sha256=lBEjMJv4VyxmeO9lHXJJazOajbFnTLak4PSBcLoPZvU,20331
35
35
  xoscar/backends/pool.py,sha256=bS_m8XBkfQQsCOaLEzM6HkV5e78dPPp1bCH6yjvPEss,62153
36
36
  xoscar/backends/router.py,sha256=EjfNpQUrhFU15eYe1kRPueziHgI2gfDViUzm7ruvXDE,10817
@@ -57,8 +57,8 @@ xoscar/collective/common.py,sha256=9c7xq3IOUvfA0I9GnpalUqXZOzmF6IEILv4zL64BYVE,3
57
57
  xoscar/collective/core.py,sha256=191aPxbUgWpjzrqyozndImDAQhZFmqoQdBkHFLDfXN0,24239
58
58
  xoscar/collective/process_group.py,sha256=kTPbrLMJSGhqbiWvTIiz-X3W0rZWd_CFn_zUIlXbOlM,23286
59
59
  xoscar/collective/utils.py,sha256=p3WEVtXvnVhkuO5mRgQBhBRFr1dKHcDKMjrbMyuiyfg,1219
60
- xoscar/collective/uv.dll,sha256=Kfh21bNGsiRUFUU3QzboWzMY9qjNCN20hhIE2X9NE3c,620544
61
- xoscar/collective/xoscar_pygloo.cp311-win_amd64.pyd,sha256=O4lY_N2xbetQ0KqH1aBc7qEWbiKrZwfziLFlkA3D3f4,831488
60
+ xoscar/collective/uv.dll,sha256=hx5H2TlMz_2KHhm4Sb2DFRMMu2sphNhitNB5dQss0Es,620544
61
+ xoscar/collective/xoscar_pygloo.cp311-win_amd64.pyd,sha256=Y7_cliGIkN0x_k-SvdX_OlDeXwiOz6Z4-kR6LrZWWIQ,781824
62
62
  xoscar/metrics/__init__.py,sha256=RjXuuYw4I2YYgD8UY2Z5yCZk0Z56xMJ1n40O80Dtxf8,726
63
63
  xoscar/metrics/api.py,sha256=dtJ4QrIqQNXhJedeqOPs4TXKgrRGZFFN50xAd9SCfec,9144
64
64
  xoscar/metrics/backends/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS3Ijp1YgyynoUFLeuU,594
@@ -69,20 +69,20 @@ xoscar/metrics/backends/prometheus/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS
69
69
  xoscar/metrics/backends/prometheus/prometheus_metric.py,sha256=65hb8O3tmsEJ7jgOrIwl_suj9SE5Tmqcfjuk0urkLvE,2120
70
70
  xoscar/serialization/__init__.py,sha256=tS8C49yrW_geWNEsbgW3phK1q4YN1ojI6CN-vroIFYM,876
71
71
  xoscar/serialization/aio.py,sha256=7YLXgkWpQ3ANy-TZ1qO8Mt4_J3cZFhFh2FEgUgxMT60,4873
72
- xoscar/serialization/core.cp311-win_amd64.pyd,sha256=n-rDdMg0A3BsZqNsXdk7EoDcx8fzDOC6F3OrXpH7SGk,267264
72
+ xoscar/serialization/core.cp311-win_amd64.pyd,sha256=2GQWKX2JXFBR7ynArn7aD4B9YIgi6ZlQyByTR_DY-OQ,265728
73
73
  xoscar/serialization/core.pxd,sha256=X-47bqBM2Kzw5SkLqICdKD0gU6CpmLsBxC3kfW--wVk,1013
74
74
  xoscar/serialization/core.pyx,sha256=ZKexLRnRwZXXn2045kR7xfM_szcoPNrDuouQCWtpFp8,30570
75
75
  xoscar/serialization/cuda.py,sha256=Fj4Cpr_YmkGceUCo0mQn8fRvmHP_5WcLdRx6epZ3RC0,3869
76
76
  xoscar/serialization/exception.py,sha256=t6yZn_Ate04UE1RbabNh7mu739sdtwarjuPXWhASx7c,1682
77
- xoscar/serialization/mlx.py,sha256=wQ1Nv524VNiGRca-bdg0QGBqD3jdUpSBhNuwdZ5cnDk,2115
77
+ xoscar/serialization/mlx.py,sha256=8QOWlYmS0eFZ1bYweDQzUkSRw5MI0dt118wOGhyGk1s,2185
78
78
  xoscar/serialization/numpy.py,sha256=C6WVx-Sdl2OHBAvVY34DFjAKXlekMbpc2ni6bR8wxYo,3001
79
79
  xoscar/serialization/pyfury.py,sha256=3ucal29Hr7PX9_1SfB2x43FE2xw_C0rLkVv3foL7qwM,1200
80
80
  xoscar/serialization/scipy.py,sha256=9ph-yoRoNiwUZTwQrn35U60VPirWlncXNAg6EXvqMR4,2554
81
81
  xoscar/virtualenv/__init__.py,sha256=rhJ7I6x7aXjKOCzSqsKLwqFJMh4YC2sqchEIJNEfI58,1151
82
82
  xoscar/virtualenv/core.py,sha256=6u7zcMiAZVOKSBUXBlJOC5pvwbmycn6svJApYMSJDIY,2943
83
83
  xoscar/virtualenv/utils.py,sha256=tZYB1kAEym5e8WK9SxhW7VgZzXk6fJMm6MoBA7pY4gM,2523
84
- xoscar/virtualenv/uv.py,sha256=CbOr9556htAvN3Jy-nO2MNIVs53tcEM6ZuYFFyFFbVw,5025
85
- xoscar-0.7.10.dist-info/METADATA,sha256=nywxpoQ_jE9MtilnDnylJ3tKP_aNt0idYXfPy7Glap0,9361
86
- xoscar-0.7.10.dist-info/WHEEL,sha256=y4n9_669c4ZQLyT56MHjc_JUbnwtaZfMVMycweN557o,102
87
- xoscar-0.7.10.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
88
- xoscar-0.7.10.dist-info/RECORD,,
84
+ xoscar/virtualenv/uv.py,sha256=auRTs098SkcunEDtwLE0XV7X2shryhqPELVXTA4Vzxs,9595
85
+ xoscar-0.7.12.dist-info/METADATA,sha256=F-Ipd2rKJIlwDI2v2kQud1slFVTjOJq3B--vJRsEjPM,9361
86
+ xoscar-0.7.12.dist-info/WHEEL,sha256=y4n9_669c4ZQLyT56MHjc_JUbnwtaZfMVMycweN557o,102
87
+ xoscar-0.7.12.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
88
+ xoscar-0.7.12.dist-info/RECORD,,