xoscar 0.7.14__cp312-cp312-win_amd64.whl → 0.7.16__cp312-cp312-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
xoscar/virtualenv/core.py CHANGED
@@ -14,10 +14,24 @@
14
14
 
15
15
  from __future__ import annotations
16
16
 
17
+ import ast
17
18
  import importlib
19
+ import operator
18
20
  from abc import ABC, abstractmethod
19
21
  from pathlib import Path
20
22
 
23
+ from packaging.markers import Marker, default_environment
24
+ from packaging.requirements import InvalidRequirement, Requirement
25
+ from packaging.version import Version
26
+
27
+ from .platform import (
28
+ check_cuda_available,
29
+ check_npu_available,
30
+ get_cuda_arch,
31
+ get_cuda_version,
32
+ )
33
+ from .utils import is_vcs_url
34
+
21
35
 
22
36
  class VirtualEnvManager(ABC):
23
37
  @classmethod
@@ -79,6 +93,13 @@ class VirtualEnvManager(ABC):
79
93
  else:
80
94
  processed.append(pkg)
81
95
 
96
+ # apply extended syntax including:
97
+ # - has_cuda: whether CUDA is available (bool)
98
+ # - cuda_version: CUDA version string, e.g. "12.1" (str)
99
+ # - cuda_arch: CUDA architecture string, e.g. "sm_80" (str)
100
+ # - has_npu: whether an NPU is available (bool)
101
+ processed = filter_requirements(processed)
102
+
82
103
  return processed
83
104
 
84
105
  @abstractmethod
@@ -96,3 +117,152 @@ class VirtualEnvManager(ABC):
96
117
  @abstractmethod
97
118
  def remove_env(self):
98
119
  pass
120
+
121
+
122
+ def get_env() -> dict[str, str | bool]:
123
+ env = default_environment().copy()
124
+ # Your custom env vars here, e.g.:
125
+ env.update(
126
+ {
127
+ "has_cuda": check_cuda_available(),
128
+ "cuda_version": get_cuda_version(),
129
+ "cuda_arch": get_cuda_arch(),
130
+ "has_npu": check_npu_available(),
131
+ }
132
+ )
133
+ return env
134
+
135
+
136
+ STANDARD_ENV_VARS = set(default_environment().keys())
137
+
138
+
139
+ def is_custom_marker(marker_str: str) -> bool:
140
+ try:
141
+ marker = Marker(marker_str)
142
+ except Exception:
143
+ return True
144
+
145
+ def traverse_markers(node):
146
+ if isinstance(node, tuple):
147
+ env_var = node[0]
148
+ if env_var not in STANDARD_ENV_VARS:
149
+ return True
150
+ return False
151
+ elif isinstance(node, list):
152
+ return any(traverse_markers(child) for child in node)
153
+ return False
154
+
155
+ return traverse_markers(marker._markers)
156
+
157
+
158
+ def eval_custom_marker(marker_str: str, env: dict) -> bool:
159
+ ops = {
160
+ ast.Eq: operator.eq,
161
+ ast.NotEq: operator.ne,
162
+ ast.Lt: operator.lt,
163
+ ast.LtE: operator.le,
164
+ ast.Gt: operator.gt,
165
+ ast.GtE: operator.ge,
166
+ ast.And: lambda a, b: a and b,
167
+ ast.Or: lambda a, b: a or b,
168
+ ast.Not: operator.not_,
169
+ }
170
+
171
+ def normalize_value(val):
172
+ # Normalize for boolean
173
+ if isinstance(val, str):
174
+ if val.lower() == "true":
175
+ return True
176
+ if val.lower() == "false":
177
+ return False
178
+
179
+ # Normalize for version-like fields
180
+ if isinstance(val, str):
181
+ if val.count(".") >= 1 and all(
182
+ part.isdigit() for part in val.split(".") if part
183
+ ):
184
+ return Version(val)
185
+
186
+ return val
187
+
188
+ def maybe_parse_cuda_arch(val):
189
+ if isinstance(val, str) and val.startswith("sm_"):
190
+ try:
191
+ return int(val[3:])
192
+ except ValueError:
193
+ return val
194
+ return val
195
+
196
+ def _eval(node):
197
+ if isinstance(node, ast.BoolOp):
198
+ left = _eval(node.values[0])
199
+ for right_node in node.values[1:]:
200
+ right = _eval(right_node)
201
+ op = ops[type(node.op)]
202
+ left = op(left, right)
203
+ return left
204
+
205
+ elif isinstance(node, ast.UnaryOp) and isinstance(node.op, ast.Not):
206
+ return not _eval(node.operand)
207
+
208
+ elif isinstance(node, ast.Compare):
209
+ left = _eval(node.left)
210
+ left = maybe_parse_cuda_arch(normalize_value(left))
211
+
212
+ for op_node, right_expr in zip(node.ops, node.comparators):
213
+ right = _eval(right_expr)
214
+ right = maybe_parse_cuda_arch(normalize_value(right))
215
+
216
+ op_func = ops[type(op_node)]
217
+ if not op_func(left, right):
218
+ return False
219
+ left = right # for chained comparisons
220
+
221
+ return True
222
+
223
+ elif isinstance(node, ast.Name):
224
+ return normalize_value(env.get(node.id))
225
+
226
+ elif isinstance(node, ast.Constant):
227
+ return node.value
228
+
229
+ elif isinstance(node, ast.Str): # Python <3.8
230
+ return node.s
231
+
232
+ else:
233
+ raise ValueError(f"Unsupported expression: {ast.dump(node)}")
234
+
235
+ tree = ast.parse(marker_str, mode="eval")
236
+ return _eval(tree.body)
237
+
238
+
239
+ def filter_requirements(requirements: list[str]) -> list[str]:
240
+ """
241
+ Filter requirements by evaluating markers in given env.
242
+ If env is None, use get_env().
243
+ """
244
+ env = get_env()
245
+ result = []
246
+ for req_str in requirements:
247
+ if is_vcs_url(req_str):
248
+ result.append(req_str)
249
+ elif ";" in req_str:
250
+ req_part, marker_part = req_str.split(";", 1)
251
+ marker_part = marker_part.strip()
252
+ try:
253
+ req = Requirement(req_str)
254
+ if req.marker is None or req.marker.evaluate(env):
255
+ result.append(f"{req.name}{req.specifier}")
256
+ continue
257
+ except InvalidRequirement:
258
+ if is_custom_marker(marker_part):
259
+ if eval_custom_marker(marker_part, env):
260
+ req = Requirement(req_part.strip())
261
+ result.append(str(req))
262
+ else:
263
+ raise
264
+ else:
265
+ req = Requirement(req_str.strip())
266
+ result.append(str(req))
267
+
268
+ return result
@@ -0,0 +1,53 @@
1
+ # Copyright 2022-2025 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
+ from typing import Optional
16
+
17
+
18
+ def check_cuda_available() -> bool:
19
+ try:
20
+ import torch
21
+
22
+ return torch.cuda.is_available()
23
+ except (ImportError, AttributeError):
24
+ return False
25
+
26
+
27
+ def get_cuda_version() -> Optional[str]:
28
+ try:
29
+ import torch
30
+
31
+ return torch.version.cuda # e.g. '12.1'
32
+ except (ImportError, AttributeError):
33
+ return None
34
+
35
+
36
+ def get_cuda_arch() -> Optional[str]:
37
+ try:
38
+ import torch
39
+
40
+ major, minor = torch.cuda.get_device_capability()
41
+ return f"sm_{major}{minor}" # e.g. 'sm_80'
42
+ except (ImportError, AttributeError):
43
+ return None
44
+
45
+
46
+ def check_npu_available() -> bool:
47
+ try:
48
+ import torch
49
+ import torch_npu # noqa: F401
50
+
51
+ return torch.npu.is_available()
52
+ except ImportError:
53
+ return False
@@ -82,3 +82,19 @@ def run_subprocess_with_logger(
82
82
  process.wait()
83
83
  for t in threads:
84
84
  t.join()
85
+
86
+
87
+ def is_vcs_url(spec_str: str) -> bool:
88
+ """
89
+ Check if the given spec string is a VCS URL.
90
+
91
+ Supports common VCS schemes like git+, svn+, hg+, bzr+, and HTTP/HTTPS URLs.
92
+
93
+ Args:
94
+ spec_str (str): The package spec string.
95
+
96
+ Returns:
97
+ bool: True if it's a VCS URL, False otherwise.
98
+ """
99
+ vcs_prefixes = ("git+", "http://", "https://", "svn+", "hg+", "bzr+")
100
+ return spec_str.startswith(vcs_prefixes)
xoscar/virtualenv/uv.py CHANGED
@@ -30,7 +30,7 @@ from packaging.requirements import Requirement
30
30
  from packaging.version import Version
31
31
 
32
32
  from .core import VirtualEnvManager
33
- from .utils import run_subprocess_with_logger
33
+ from .utils import is_vcs_url, run_subprocess_with_logger
34
34
 
35
35
  UV_PATH = os.getenv("XOSCAR_UV_PATH")
36
36
  SKIP_INSTALLED = bool(int(os.getenv("XOSCAR_VIRTUAL_ENV_SKIP_INSTALLED", "0")))
@@ -163,9 +163,7 @@ class UVVirtualEnvManager(VirtualEnvManager):
163
163
 
164
164
  for spec_str in specs:
165
165
  # skip git+xxx
166
- if spec_str.startswith(
167
- ("git+", "http://", "https://", "svn+", "hg+", "bzr+")
168
- ):
166
+ if is_vcs_url(spec_str):
169
167
  keep.append(spec_str)
170
168
  continue
171
169
 
@@ -241,6 +239,9 @@ class UVVirtualEnvManager(VirtualEnvManager):
241
239
  return
242
240
 
243
241
  packages = self.process_packages(packages)
242
+ if not packages:
243
+ return
244
+
244
245
  log = kwargs.pop("log", False)
245
246
  skip_installed = kwargs.pop("skip_installed", SKIP_INSTALLED)
246
247
  uv_path = self._get_uv_path()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: xoscar
3
- Version: 0.7.14
3
+ Version: 0.7.16
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.cp312-win_amd64.pyd,sha256=zNArBk8gp_Y9YLdAnvSps_cJWmjw3v3tNS_YE_Ztbbs,109056
2
+ xoscar/_utils.cp312-win_amd64.pyd,sha256=WtRynvXS6-Yo41eZ3P8-Yd1i3O3xYIRVc83JKiunTW8,109056
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.cp312-win_amd64.pyd,sha256=uo4ksh66-F5KxmjkQk8wTjKVfVYNl2vT0XSR5CQLCQ0,155648
10
+ xoscar/context.cp312-win_amd64.pyd,sha256=6y6IIoRmKZBslEdiFCnvBrVoNL2YadLTmKF9kGePoJI,154624
11
11
  xoscar/context.pxd,sha256=6n6IAbmArSRq8EjcsbS6npW8xP1jI0qOoS1fF0oyj-o,746
12
12
  xoscar/context.pyx,sha256=FOJVerGOvxe2USryXEQA0rpaFX_ScxISH6QWKUcahY8,11310
13
- xoscar/core.cp312-win_amd64.pyd,sha256=JgYWbo9bBZmaVd1eqMAQCMuI7qjF7PNutfZmatbcoaA,312832
13
+ xoscar/core.cp312-win_amd64.pyd,sha256=WQw9k9ndPs7cv9IO1wxLYMokn8v-YC2p5BJtSTUmIkc,312832
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.cp312-win_amd64.pyd,sha256=kqRsw5Sp71mkKaGRvZeOGBalN23c9WR0Of4kgVmxDew,249344
33
+ xoscar/backends/message.cp312-win_amd64.pyd,sha256=rWwyz2BYDoR1fLmuh3HLJllXQNpru8DiG4VaMQc0iKU,249344
34
34
  xoscar/backends/message.pyi,sha256=m1PrSLvj-IbrHuVfQGoPDs6prI-GJV1vQJqZ5WdQcY4,6798
35
35
  xoscar/backends/message.pyx,sha256=lBEjMJv4VyxmeO9lHXJJazOajbFnTLak4PSBcLoPZvU,20331
36
36
  xoscar/backends/pool.py,sha256=bS_m8XBkfQQsCOaLEzM6HkV5e78dPPp1bCH6yjvPEss,62153
@@ -58,8 +58,8 @@ xoscar/collective/common.py,sha256=9c7xq3IOUvfA0I9GnpalUqXZOzmF6IEILv4zL64BYVE,3
58
58
  xoscar/collective/core.py,sha256=191aPxbUgWpjzrqyozndImDAQhZFmqoQdBkHFLDfXN0,24239
59
59
  xoscar/collective/process_group.py,sha256=kTPbrLMJSGhqbiWvTIiz-X3W0rZWd_CFn_zUIlXbOlM,23286
60
60
  xoscar/collective/utils.py,sha256=p3WEVtXvnVhkuO5mRgQBhBRFr1dKHcDKMjrbMyuiyfg,1219
61
- xoscar/collective/uv.dll,sha256=2squIX2fZQILorrLAPcs4ep3bXPDkzxrs65prgKjjyo,620544
62
- xoscar/collective/xoscar_pygloo.cp312-win_amd64.pyd,sha256=p7j0lOKJnHb0w45CK0yaQ3DNa9Lg2ubTsWnqp4jmnZY,795136
61
+ xoscar/collective/uv.dll,sha256=OU7XZMUucvo09aCZagbmsLeoKhyvRDnf41Lsg4RUjJo,620544
62
+ xoscar/collective/xoscar_pygloo.cp312-win_amd64.pyd,sha256=QXMcEsTJcPQrt6Pp8NFhyzVBtd_1-9kGuvP8x0HmCDY,795136
63
63
  xoscar/collective/xoscar_pygloo.pyi,sha256=6KRzElgNBBKWh-VivUw1b5Dolp17MgwA91hQo33EysU,7616
64
64
  xoscar/metrics/__init__.py,sha256=RjXuuYw4I2YYgD8UY2Z5yCZk0Z56xMJ1n40O80Dtxf8,726
65
65
  xoscar/metrics/api.py,sha256=dtJ4QrIqQNXhJedeqOPs4TXKgrRGZFFN50xAd9SCfec,9144
@@ -71,7 +71,7 @@ xoscar/metrics/backends/prometheus/__init__.py,sha256=ZHepfhCDRuK9yz4pAM7bjpWDvS
71
71
  xoscar/metrics/backends/prometheus/prometheus_metric.py,sha256=65hb8O3tmsEJ7jgOrIwl_suj9SE5Tmqcfjuk0urkLvE,2120
72
72
  xoscar/serialization/__init__.py,sha256=tS8C49yrW_geWNEsbgW3phK1q4YN1ojI6CN-vroIFYM,876
73
73
  xoscar/serialization/aio.py,sha256=7YLXgkWpQ3ANy-TZ1qO8Mt4_J3cZFhFh2FEgUgxMT60,4873
74
- xoscar/serialization/core.cp312-win_amd64.pyd,sha256=9pDGvbDOeh8ginzlezaXpFylKagRe3EROVkTtghdzi0,268800
74
+ xoscar/serialization/core.cp312-win_amd64.pyd,sha256=1soyzImurs93FcLF84oL5qqJK7LGxiImqEmR61EchIY,268800
75
75
  xoscar/serialization/core.pxd,sha256=X-47bqBM2Kzw5SkLqICdKD0gU6CpmLsBxC3kfW--wVk,1013
76
76
  xoscar/serialization/core.pyi,sha256=Zof9373qy2lmjenSuMznEiTSCNW6WQB7rmSXrRbjUo0,1931
77
77
  xoscar/serialization/core.pyx,sha256=ZKexLRnRwZXXn2045kR7xfM_szcoPNrDuouQCWtpFp8,30570
@@ -82,10 +82,11 @@ xoscar/serialization/numpy.py,sha256=C6WVx-Sdl2OHBAvVY34DFjAKXlekMbpc2ni6bR8wxYo
82
82
  xoscar/serialization/pyfury.py,sha256=3ucal29Hr7PX9_1SfB2x43FE2xw_C0rLkVv3foL7qwM,1200
83
83
  xoscar/serialization/scipy.py,sha256=9ph-yoRoNiwUZTwQrn35U60VPirWlncXNAg6EXvqMR4,2554
84
84
  xoscar/virtualenv/__init__.py,sha256=rhJ7I6x7aXjKOCzSqsKLwqFJMh4YC2sqchEIJNEfI58,1151
85
- xoscar/virtualenv/core.py,sha256=5w1UDnzLHKyrFFwqAJFXVxkpXrd5ux8OlxSR3971bMo,3055
86
- xoscar/virtualenv/utils.py,sha256=tZYB1kAEym5e8WK9SxhW7VgZzXk6fJMm6MoBA7pY4gM,2523
87
- xoscar/virtualenv/uv.py,sha256=irejdyLJRMZbojo_DZqzbK0xGiB5yG7mGNGOIen2I1s,11439
88
- xoscar-0.7.14.dist-info/METADATA,sha256=NQ59QZ4x5-hjqJVEHkZeljXDSXRiCNnaU3bhqoVl428,9418
89
- xoscar-0.7.14.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
90
- xoscar-0.7.14.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
91
- xoscar-0.7.14.dist-info/RECORD,,
85
+ xoscar/virtualenv/core.py,sha256=nRfOcKQbb-4TjtLmeMepFnMPLySJAIFwFJsXvXnNv44,8366
86
+ xoscar/virtualenv/platform.py,sha256=rkcqR_lTVJh3AVlP5TJ0NmUKbKKw47S56gRiHPDRimI,1456
87
+ xoscar/virtualenv/utils.py,sha256=WzhEnwgGNQV5sRqZrdvCyQPcJqI5V9feBLM_Mr7UD-w,2975
88
+ xoscar/virtualenv/uv.py,sha256=m95UyJ9BnWHqAoRI_yT1PFB11ulr_CS_pBd_gKkOkyU,11412
89
+ xoscar-0.7.16.dist-info/METADATA,sha256=5o-eYRTi_zPnn_28A7C5awwsOvu--sl0ZuRphbJnVCE,9418
90
+ xoscar-0.7.16.dist-info/WHEEL,sha256=8UP9x9puWI0P1V_d7K2oMTBqfeLNm21CTzZ_Ptr0NXU,101
91
+ xoscar-0.7.16.dist-info/top_level.txt,sha256=vYlqqY4Nys8Thm1hePIuUv8eQePdULVWMmt7lXtX_ZA,21
92
+ xoscar-0.7.16.dist-info/RECORD,,