a3s-code 8.0.1__tar.gz → 8.0.3__tar.gz

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.
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.4
2
+ Name: a3s-code
3
+ Version: 8.0.3
4
+ Summary: A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases
5
+ Author: A3S Lab
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/A3S-Lab/Code
8
+ Project-URL: Repository, https://github.com/A3S-Lab/Code
9
+ Project-URL: Issues, https://github.com/A3S-Lab/Code/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: Implementation :: CPython
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Topic :: Software Development
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+
23
+ # a3s-code (Python bootstrap)
24
+
25
+ `pip install a3s-code` ships this small pure-Python package. On first
26
+ `import a3s_code` it downloads the native extension matching your
27
+ platform from the project's
28
+ [GitHub Releases](https://github.com/A3S-Lab/Code/releases), verifies
29
+ the wheel's sha256 against the release manifest, extracts the compiled
30
+ extension into a per-user cache, and exposes the normal `a3s_code` API.
31
+
32
+ The v8.0.3 release uses one CPython 3.10 stable-ABI (`cp310-abi3`) wheel per
33
+ platform. That wheel is installable by CPython 3.10, 3.11, 3.12, 3.13, and
34
+ 3.14. The published `v8.0.2` assets predate this workflow and still use exact
35
+ CPython 3.10–3.13 wheel names; upgrade the bootstrap to v8.0.3 for Python
36
+ 3.14. The loader falls back to the exact per-minor names used by older
37
+ releases, so upgrading the bootstrap does not invalidate an older release
38
+ asset.
39
+
40
+ Subsequent imports use the cached extension. Cache lives under a
41
+ platform-specific directory, `~/.cache/a3s-code/<version>/<platform-tag>/`
42
+ (or `$A3S_CODE_CACHE_DIR/<version>/<platform-tag>/` when overridden).
43
+
44
+ ## Why
45
+
46
+ PyPI imposes a default 10 GB per-project storage cap. A Rust SDK with
47
+ ~17 MB native wheels per Python × platform tripped that limit. GitHub
48
+ Releases is the canonical wheel host; this bootstrap keeps
49
+ `pip install a3s-code` working without dragging the native wheels back
50
+ through PyPI.
51
+
52
+ ## Supported platforms
53
+
54
+ - macOS arm64 (Apple Silicon, macOS 11+)
55
+ - macOS x86_64 (Intel, macOS 12+)
56
+ - Linux x86_64 (glibc 2.28+)
57
+ - Windows x86_64
58
+
59
+ CPython 3.10, 3.11, 3.12, 3.13, and 3.14.
60
+
61
+ The bootstrap itself needs a working pip in the interpreter that runs it. If
62
+ `python3.14 -m pip` reports `No module named pip`, initialize pip and retry:
63
+
64
+ ```bash
65
+ python3.14 -m ensurepip --upgrade
66
+ python3.14 -m pip install --upgrade pip
67
+ python3.14 -m pip install a3s-code
68
+ ```
69
+
70
+ ## Environment overrides
71
+
72
+ | Variable | Effect |
73
+ |---|---|
74
+ | `A3S_CODE_CACHE_DIR` | Cache root (defaults to `$XDG_CACHE_HOME/a3s-code` or `~/.cache/a3s-code`) |
75
+ | `A3S_CODE_RELEASES_BASE_URL` | Override the release base URL — useful for air-gapped mirrors |
76
+ | `A3S_CODE_SKIP_HASH_CHECK` | `1` skips sha256 verification (do not use in production) |
77
+
78
+ ## Manual install
79
+
80
+ If you do not want the bootstrap to phone home, install the native
81
+ wheel directly:
82
+
83
+ ```bash
84
+ pip install \
85
+ 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp310-abi3-manylinux_2_28_x86_64.whl'
86
+ ```
87
+
88
+ For an Intel Mac on macOS 12 or later, use the `macosx_12_0_x86_64` asset:
89
+
90
+ ```bash
91
+ pip install \
92
+ 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp310-abi3-macosx_12_0_x86_64.whl'
93
+ ```
94
+
95
+ Replace `<VERSION>` with the release to install. The Intel asset is available
96
+ from the first release produced with the Intel build matrix.
97
+
98
+ The Intel macOS 12 build does not ship the optional local ONNX embedding
99
+ adapter. Keep retrieval model-free or configure an explicitly authorized
100
+ remote embedding provider when using that platform.
@@ -0,0 +1,78 @@
1
+ # a3s-code (Python bootstrap)
2
+
3
+ `pip install a3s-code` ships this small pure-Python package. On first
4
+ `import a3s_code` it downloads the native extension matching your
5
+ platform from the project's
6
+ [GitHub Releases](https://github.com/A3S-Lab/Code/releases), verifies
7
+ the wheel's sha256 against the release manifest, extracts the compiled
8
+ extension into a per-user cache, and exposes the normal `a3s_code` API.
9
+
10
+ The v8.0.3 release uses one CPython 3.10 stable-ABI (`cp310-abi3`) wheel per
11
+ platform. That wheel is installable by CPython 3.10, 3.11, 3.12, 3.13, and
12
+ 3.14. The published `v8.0.2` assets predate this workflow and still use exact
13
+ CPython 3.10–3.13 wheel names; upgrade the bootstrap to v8.0.3 for Python
14
+ 3.14. The loader falls back to the exact per-minor names used by older
15
+ releases, so upgrading the bootstrap does not invalidate an older release
16
+ asset.
17
+
18
+ Subsequent imports use the cached extension. Cache lives under a
19
+ platform-specific directory, `~/.cache/a3s-code/<version>/<platform-tag>/`
20
+ (or `$A3S_CODE_CACHE_DIR/<version>/<platform-tag>/` when overridden).
21
+
22
+ ## Why
23
+
24
+ PyPI imposes a default 10 GB per-project storage cap. A Rust SDK with
25
+ ~17 MB native wheels per Python × platform tripped that limit. GitHub
26
+ Releases is the canonical wheel host; this bootstrap keeps
27
+ `pip install a3s-code` working without dragging the native wheels back
28
+ through PyPI.
29
+
30
+ ## Supported platforms
31
+
32
+ - macOS arm64 (Apple Silicon, macOS 11+)
33
+ - macOS x86_64 (Intel, macOS 12+)
34
+ - Linux x86_64 (glibc 2.28+)
35
+ - Windows x86_64
36
+
37
+ CPython 3.10, 3.11, 3.12, 3.13, and 3.14.
38
+
39
+ The bootstrap itself needs a working pip in the interpreter that runs it. If
40
+ `python3.14 -m pip` reports `No module named pip`, initialize pip and retry:
41
+
42
+ ```bash
43
+ python3.14 -m ensurepip --upgrade
44
+ python3.14 -m pip install --upgrade pip
45
+ python3.14 -m pip install a3s-code
46
+ ```
47
+
48
+ ## Environment overrides
49
+
50
+ | Variable | Effect |
51
+ |---|---|
52
+ | `A3S_CODE_CACHE_DIR` | Cache root (defaults to `$XDG_CACHE_HOME/a3s-code` or `~/.cache/a3s-code`) |
53
+ | `A3S_CODE_RELEASES_BASE_URL` | Override the release base URL — useful for air-gapped mirrors |
54
+ | `A3S_CODE_SKIP_HASH_CHECK` | `1` skips sha256 verification (do not use in production) |
55
+
56
+ ## Manual install
57
+
58
+ If you do not want the bootstrap to phone home, install the native
59
+ wheel directly:
60
+
61
+ ```bash
62
+ pip install \
63
+ 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp310-abi3-manylinux_2_28_x86_64.whl'
64
+ ```
65
+
66
+ For an Intel Mac on macOS 12 or later, use the `macosx_12_0_x86_64` asset:
67
+
68
+ ```bash
69
+ pip install \
70
+ 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp310-abi3-macosx_12_0_x86_64.whl'
71
+ ```
72
+
73
+ Replace `<VERSION>` with the release to install. The Intel asset is available
74
+ from the first release produced with the Intel build matrix.
75
+
76
+ The Intel macOS 12 build does not ship the optional local ONNX embedding
77
+ adapter. Keep retrieval model-free or configure an explicitly authorized
78
+ remote embedding provider when using that platform.
@@ -7,7 +7,7 @@ name = "a3s-code"
7
7
  # Keep in sync with crates/code core release. The bootstrap loader fetches
8
8
  # the matching native wheel from `https://github.com/A3S-Lab/Code/releases/tag/v<version>`
9
9
  # at import time.
10
- version = "8.0.1"
10
+ version = "8.0.3"
11
11
  description = "A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases"
12
12
  readme = "README.md"
13
13
  license = {text = "MIT"}
@@ -18,6 +18,11 @@ authors = [
18
18
  classifiers = [
19
19
  "Programming Language :: Python :: 3",
20
20
  "Programming Language :: Python :: Implementation :: CPython",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ "Programming Language :: Python :: 3.13",
25
+ "Programming Language :: Python :: 3.14",
21
26
  "License :: OSI Approved :: MIT License",
22
27
  "Operating System :: OS Independent",
23
28
  "Topic :: Software Development",
@@ -10,9 +10,8 @@ from . import _bootstrap as _bootstrap
10
10
 
11
11
  _bootstrap.ensure_native_loaded()
12
12
 
13
- # Re-import after the cache dir is on sys.path. The bootstrap extracted
14
- # `_native.<abi>.so` into a per-version cache; Python's import machinery
15
- # picks it up from there.
13
+ # The bootstrap extracted `_native.<abi>.so` into a per-version cache and
14
+ # registered it explicitly as `a3s_code._native` before returning.
16
15
  from ._native import * # noqa: E402,F401,F403
17
16
 
18
17
  __version__ = _bootstrap.__version__
@@ -1,12 +1,12 @@
1
1
  """Lazy loader for the a3s-code native extension.
2
2
 
3
3
  This module is part of the pure-Python bootstrap published to PyPI under
4
- the `a3s-code` name. On first import it resolves the matching native
5
- wheel for the current interpreter/platform, downloads it from the
6
- project's GitHub Releases, verifies the wheel's sha256 against the
4
+ the `a3s-code` name. On first import it resolves a compatible native
5
+ wheel for the current platform, downloads it from the project's GitHub
6
+ Releases, verifies the wheel's sha256 against the
7
7
  release manifest, extracts the compiled `_native` extension into a
8
- per-user cache, and prepends the cache to `sys.path` so the rest of
9
- `a3s_code/__init__.py` can `from ._native import *` normally.
8
+ per-user cache, and registers it explicitly as `a3s_code._native` because it
9
+ lives outside the installed package directory.
10
10
 
11
11
  Override the cache location via `A3S_CODE_CACHE_DIR`. Override the
12
12
  release source via `A3S_CODE_RELEASES_BASE_URL` (default points at the
@@ -31,11 +31,13 @@ from typing import Optional
31
31
 
32
32
  # Version is the bootstrap's own version, which equals the matching native
33
33
  # wheel version on GH Releases. Bumped by the release workflow.
34
- __version__ = "8.0.1"
34
+ __version__ = "8.0.3"
35
35
 
36
36
  _DEFAULT_BASE_URL = "https://github.com/A3S-Lab/Code/releases/download"
37
37
  _REQUEST_TIMEOUT_S = 120
38
38
  _USER_AGENT = f"a3s-code-bootstrap/{__version__}"
39
+ _MIN_PYTHON = (3, 10)
40
+ _ABI3_PYTHON_TAG = "cp310-abi3"
39
41
  _LOAD_LOCK = threading.Lock()
40
42
  _LOADED = False
41
43
 
@@ -44,6 +46,15 @@ class BootstrapError(RuntimeError):
44
46
  """Raised when the native extension cannot be located, downloaded, or verified."""
45
47
 
46
48
 
49
+ class BootstrapHttpError(BootstrapError):
50
+ """HTTP failure with a status code that callers can safely classify."""
51
+
52
+ def __init__(self, url: str, status_code: int):
53
+ self.url = url
54
+ self.status_code = status_code
55
+ super().__init__(f"GET {url} failed: HTTP {status_code}")
56
+
57
+
47
58
  def _base_url() -> str:
48
59
  return os.environ.get("A3S_CODE_RELEASES_BASE_URL", _DEFAULT_BASE_URL).rstrip("/")
49
60
 
@@ -51,9 +62,18 @@ def _base_url() -> str:
51
62
  def _cache_root() -> Path:
52
63
  override = os.environ.get("A3S_CODE_CACHE_DIR")
53
64
  if override:
54
- return Path(override).expanduser() / __version__
55
- base = os.environ.get("XDG_CACHE_HOME") or str(Path.home() / ".cache")
56
- return Path(base) / "a3s-code" / __version__
65
+ base = Path(override).expanduser() / __version__
66
+ else:
67
+ base = (
68
+ Path(os.environ.get("XDG_CACHE_HOME") or str(Path.home() / ".cache"))
69
+ / "a3s-code"
70
+ / __version__
71
+ )
72
+ # Keep native binaries for different architectures/OS baselines isolated.
73
+ # This matters when an Apple Silicon and an Intel interpreter share a home
74
+ # directory (for example, under Rosetta); a cached arm64 extension must
75
+ # never be handed to an x86_64 process.
76
+ return base / _platform_tag()
57
77
 
58
78
 
59
79
  def _platform_tag() -> str:
@@ -68,6 +88,10 @@ def _platform_tag() -> str:
68
88
  if sys_plat == "darwin":
69
89
  if machine in ("arm64", "aarch64"):
70
90
  return "macosx_11_0_arm64"
91
+ if machine in ("x86_64", "amd64"):
92
+ # Intel wheels are built with MACOSX_DEPLOYMENT_TARGET=12.0 so
93
+ # they can run on supported Intel Macs back to macOS 12.
94
+ return "macosx_12_0_x86_64"
71
95
  elif sys_plat == "linux":
72
96
  if machine in ("x86_64", "amd64"):
73
97
  return "manylinux_2_28_x86_64"
@@ -76,15 +100,56 @@ def _platform_tag() -> str:
76
100
  return "win_amd64"
77
101
  raise BootstrapError(
78
102
  f"a3s-code: no native wheel published for {sys_plat}/{machine}. "
79
- "Supported platforms: macOS arm64, Linux x86_64 (glibc 2.28+), Windows x86_64."
103
+ "Supported platforms: macOS arm64 (11+), macOS Intel (12+), "
104
+ "Linux x86_64 (glibc 2.28+), Windows x86_64."
80
105
  )
81
106
 
82
107
 
83
108
  def _wheel_filename(version: str = __version__) -> str:
109
+ if platform.python_implementation() != "CPython":
110
+ raise BootstrapError(
111
+ "a3s-code publishes native wheels for CPython only; "
112
+ f"found {platform.python_implementation()}"
113
+ )
114
+ if (sys.version_info.major, sys.version_info.minor) < _MIN_PYTHON:
115
+ raise BootstrapError(
116
+ "a3s-code requires CPython 3.10 or newer; "
117
+ f"found {sys.version_info.major}.{sys.version_info.minor}"
118
+ )
84
119
  py_tag = f"cp{sys.version_info.major}{sys.version_info.minor}"
85
120
  return f"a3s_code-{version}-{py_tag}-{py_tag}-{_platform_tag()}.whl"
86
121
 
87
122
 
123
+ def _abi3_wheel_filename(version: str = __version__) -> str:
124
+ """Return the stable-ABI wheel name used by current releases."""
125
+ if platform.python_implementation() != "CPython":
126
+ raise BootstrapError(
127
+ "a3s-code publishes native wheels for CPython only; "
128
+ f"found {platform.python_implementation()}"
129
+ )
130
+ if (sys.version_info.major, sys.version_info.minor) < _MIN_PYTHON:
131
+ raise BootstrapError(
132
+ "a3s-code requires CPython 3.10 or newer; "
133
+ f"found {sys.version_info.major}.{sys.version_info.minor}"
134
+ )
135
+ return f"a3s_code-{version}-{_ABI3_PYTHON_TAG}-{_platform_tag()}.whl"
136
+
137
+
138
+ def _wheel_candidates(version: str = __version__) -> tuple[str, ...]:
139
+ """Return compatible wheel names in migration-safe preference order.
140
+
141
+ Existing releases contain one wheel per CPython minor, so Python 3.10–3.13
142
+ keep using those exact assets first. New releases publish a single
143
+ ``cp310-abi3`` wheel; Python 3.14+ prefers that asset and all interpreters
144
+ fall back to it when an older release has no exact match.
145
+ """
146
+ exact = _wheel_filename(version)
147
+ abi3 = _abi3_wheel_filename(version)
148
+ if sys.version_info.minor >= 14:
149
+ return (abi3, exact)
150
+ return (exact, abi3)
151
+
152
+
88
153
  def _release_url(filename: str, version: str = __version__) -> str:
89
154
  return f"{_base_url()}/v{version}/{filename}"
90
155
 
@@ -95,7 +160,7 @@ def _http_get(url: str) -> bytes:
95
160
  with urllib.request.urlopen(req, timeout=_REQUEST_TIMEOUT_S) as resp:
96
161
  return resp.read()
97
162
  except urllib.error.HTTPError as exc:
98
- raise BootstrapError(f"GET {url} failed: HTTP {exc.code}") from exc
163
+ raise BootstrapHttpError(url, exc.code) from exc
99
164
  except urllib.error.URLError as exc:
100
165
  raise BootstrapError(f"GET {url} failed: {exc.reason}") from exc
101
166
 
@@ -121,6 +186,27 @@ def _expected_sha256(wheel_name: str, version: str = __version__) -> Optional[st
121
186
  return None
122
187
 
123
188
 
189
+ def _download_wheel(version: str) -> tuple[str, bytes]:
190
+ """Download the first compatible wheel, retaining old-release fallback."""
191
+ candidates = _wheel_candidates(version)
192
+ not_found: list[str] = []
193
+ for wheel_name in candidates:
194
+ try:
195
+ return wheel_name, _http_get(_release_url(wheel_name, version))
196
+ except BootstrapHttpError as exc:
197
+ if exc.status_code == 404:
198
+ not_found.append(wheel_name)
199
+ continue
200
+ raise
201
+
202
+ tried = ", ".join(not_found)
203
+ raise BootstrapError(
204
+ "a3s-code: no compatible native wheel was published for "
205
+ f"CPython {sys.version_info.major}.{sys.version_info.minor} on "
206
+ f"{sys.platform}/{platform.machine()}. Tried: {tried}"
207
+ )
208
+
209
+
124
210
  def _extract_native(wheel_bytes: bytes, target_dir: Path) -> Path:
125
211
  """Extract the compiled `_native.*` extension from `wheel_bytes` into
126
212
  `target_dir`. Returns the path to the extracted file.
@@ -144,9 +230,23 @@ def _extract_native(wheel_bytes: bytes, target_dir: Path) -> Path:
144
230
  def _find_cached_native(cache_dir: Path) -> Optional[Path]:
145
231
  if not cache_dir.is_dir():
146
232
  return None
147
- for child in cache_dir.iterdir():
148
- if child.is_file() and child.name.startswith("_native."):
149
- return child
233
+ exact_tag = f"cp{sys.version_info.major}{sys.version_info.minor}"
234
+ cpython_tag = f"cpython-{sys.version_info.major}{sys.version_info.minor}"
235
+ exact: list[Path] = []
236
+ abi3: list[Path] = []
237
+ for child in sorted(cache_dir.iterdir()):
238
+ if not child.is_file() or not child.name.startswith("_native."):
239
+ continue
240
+ name = child.name.lower()
241
+ if f".{exact_tag}" in name or cpython_tag in name:
242
+ exact.append(child)
243
+ elif ".abi3." in name or name.endswith(".abi3"):
244
+ abi3.append(child)
245
+ # Prefer a native build tied to this interpreter, then the stable ABI.
246
+ if exact:
247
+ return exact[0]
248
+ if abi3:
249
+ return abi3[0]
150
250
  return None
151
251
 
152
252
 
@@ -188,13 +288,12 @@ def ensure_native_loaded(version: str = __version__) -> Path:
188
288
 
189
289
  native = _find_cached_native(cache)
190
290
  if native is None:
191
- wheel_name = _wheel_filename(version)
291
+ wheel_name, wheel_bytes = _download_wheel(version)
192
292
  url = _release_url(wheel_name, version)
193
293
  sys.stderr.write(
194
294
  f"a3s-code: fetching native wheel {wheel_name} "
195
295
  f"from {url} (first import only)...\n"
196
296
  )
197
- wheel_bytes = _http_get(url)
198
297
 
199
298
  if os.environ.get("A3S_CODE_SKIP_HASH_CHECK") != "1":
200
299
  expected = _expected_sha256(wheel_name, version)
@@ -0,0 +1,100 @@
1
+ Metadata-Version: 2.4
2
+ Name: a3s-code
3
+ Version: 8.0.3
4
+ Summary: A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases
5
+ Author: A3S Lab
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/A3S-Lab/Code
8
+ Project-URL: Repository, https://github.com/A3S-Lab/Code
9
+ Project-URL: Issues, https://github.com/A3S-Lab/Code/issues
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: Implementation :: CPython
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Classifier: Programming Language :: Python :: 3.13
16
+ Classifier: Programming Language :: Python :: 3.14
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Topic :: Software Development
20
+ Requires-Python: >=3.10
21
+ Description-Content-Type: text/markdown
22
+
23
+ # a3s-code (Python bootstrap)
24
+
25
+ `pip install a3s-code` ships this small pure-Python package. On first
26
+ `import a3s_code` it downloads the native extension matching your
27
+ platform from the project's
28
+ [GitHub Releases](https://github.com/A3S-Lab/Code/releases), verifies
29
+ the wheel's sha256 against the release manifest, extracts the compiled
30
+ extension into a per-user cache, and exposes the normal `a3s_code` API.
31
+
32
+ The v8.0.3 release uses one CPython 3.10 stable-ABI (`cp310-abi3`) wheel per
33
+ platform. That wheel is installable by CPython 3.10, 3.11, 3.12, 3.13, and
34
+ 3.14. The published `v8.0.2` assets predate this workflow and still use exact
35
+ CPython 3.10–3.13 wheel names; upgrade the bootstrap to v8.0.3 for Python
36
+ 3.14. The loader falls back to the exact per-minor names used by older
37
+ releases, so upgrading the bootstrap does not invalidate an older release
38
+ asset.
39
+
40
+ Subsequent imports use the cached extension. Cache lives under a
41
+ platform-specific directory, `~/.cache/a3s-code/<version>/<platform-tag>/`
42
+ (or `$A3S_CODE_CACHE_DIR/<version>/<platform-tag>/` when overridden).
43
+
44
+ ## Why
45
+
46
+ PyPI imposes a default 10 GB per-project storage cap. A Rust SDK with
47
+ ~17 MB native wheels per Python × platform tripped that limit. GitHub
48
+ Releases is the canonical wheel host; this bootstrap keeps
49
+ `pip install a3s-code` working without dragging the native wheels back
50
+ through PyPI.
51
+
52
+ ## Supported platforms
53
+
54
+ - macOS arm64 (Apple Silicon, macOS 11+)
55
+ - macOS x86_64 (Intel, macOS 12+)
56
+ - Linux x86_64 (glibc 2.28+)
57
+ - Windows x86_64
58
+
59
+ CPython 3.10, 3.11, 3.12, 3.13, and 3.14.
60
+
61
+ The bootstrap itself needs a working pip in the interpreter that runs it. If
62
+ `python3.14 -m pip` reports `No module named pip`, initialize pip and retry:
63
+
64
+ ```bash
65
+ python3.14 -m ensurepip --upgrade
66
+ python3.14 -m pip install --upgrade pip
67
+ python3.14 -m pip install a3s-code
68
+ ```
69
+
70
+ ## Environment overrides
71
+
72
+ | Variable | Effect |
73
+ |---|---|
74
+ | `A3S_CODE_CACHE_DIR` | Cache root (defaults to `$XDG_CACHE_HOME/a3s-code` or `~/.cache/a3s-code`) |
75
+ | `A3S_CODE_RELEASES_BASE_URL` | Override the release base URL — useful for air-gapped mirrors |
76
+ | `A3S_CODE_SKIP_HASH_CHECK` | `1` skips sha256 verification (do not use in production) |
77
+
78
+ ## Manual install
79
+
80
+ If you do not want the bootstrap to phone home, install the native
81
+ wheel directly:
82
+
83
+ ```bash
84
+ pip install \
85
+ 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp310-abi3-manylinux_2_28_x86_64.whl'
86
+ ```
87
+
88
+ For an Intel Mac on macOS 12 or later, use the `macosx_12_0_x86_64` asset:
89
+
90
+ ```bash
91
+ pip install \
92
+ 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp310-abi3-macosx_12_0_x86_64.whl'
93
+ ```
94
+
95
+ Replace `<VERSION>` with the release to install. The Intel asset is available
96
+ from the first release produced with the Intel build matrix.
97
+
98
+ The Intel macOS 12 build does not ship the optional local ONNX embedding
99
+ adapter. Keep retrieval model-free or configure an explicitly authorized
100
+ remote embedding provider when using that platform.
@@ -75,6 +75,61 @@ class WheelFilenameTests(unittest.TestCase):
75
75
  "a3s_code-3.2.1-cp311-cp311-macosx_11_0_arm64.whl",
76
76
  )
77
77
 
78
+ def test_macos_intel_cp312(self):
79
+ self.assertEqual(
80
+ self._filename_for("darwin", "x86_64", 12),
81
+ "a3s_code-3.2.1-cp312-cp312-macosx_12_0_x86_64.whl",
82
+ )
83
+
84
+ def test_macos_intel_abi3(self):
85
+ with (
86
+ mock.patch.object(sys, "platform", "darwin"),
87
+ mock.patch.object(_bootstrap.platform, "machine", return_value="x86_64"),
88
+ mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 14)),
89
+ ):
90
+ self.assertEqual(
91
+ _bootstrap._abi3_wheel_filename("3.2.1"),
92
+ "a3s_code-3.2.1-cp310-abi3-macosx_12_0_x86_64.whl",
93
+ )
94
+
95
+ def test_new_python_prefers_abi3_then_exact_fallback(self):
96
+ with (
97
+ mock.patch.object(sys, "platform", "darwin"),
98
+ mock.patch.object(_bootstrap.platform, "machine", return_value="x86_64"),
99
+ mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 14)),
100
+ ):
101
+ self.assertEqual(
102
+ _bootstrap._wheel_candidates("3.2.1"),
103
+ (
104
+ "a3s_code-3.2.1-cp310-abi3-macosx_12_0_x86_64.whl",
105
+ "a3s_code-3.2.1-cp314-cp314-macosx_12_0_x86_64.whl",
106
+ ),
107
+ )
108
+
109
+ def test_existing_python_prefers_exact_then_abi3(self):
110
+ with (
111
+ mock.patch.object(sys, "platform", "darwin"),
112
+ mock.patch.object(_bootstrap.platform, "machine", return_value="x86_64"),
113
+ mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 12)),
114
+ ):
115
+ self.assertEqual(
116
+ _bootstrap._wheel_candidates("3.2.1"),
117
+ (
118
+ "a3s_code-3.2.1-cp312-cp312-macosx_12_0_x86_64.whl",
119
+ "a3s_code-3.2.1-cp310-abi3-macosx_12_0_x86_64.whl",
120
+ ),
121
+ )
122
+
123
+ def test_python_below_abi3_floor_raises(self):
124
+ with (
125
+ mock.patch.object(sys, "platform", "darwin"),
126
+ mock.patch.object(_bootstrap.platform, "machine", return_value="x86_64"),
127
+ mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 9)),
128
+ ):
129
+ with self.assertRaises(_bootstrap.BootstrapError) as cm:
130
+ _bootstrap._wheel_candidates("3.2.1")
131
+ self.assertIn("CPython 3.10 or newer", str(cm.exception))
132
+
78
133
  def test_windows_amd64_cp313(self):
79
134
  self.assertEqual(
80
135
  self._filename_for("win32", "AMD64", 13),
@@ -108,18 +163,31 @@ class CacheDirTests(unittest.TestCase):
108
163
 
109
164
  def test_default_uses_xdg_or_home(self):
110
165
  cache = _bootstrap._cache_root()
111
- self.assertEqual(cache.parts[-2:], ("a3s-code", _bootstrap.__version__))
166
+ self.assertEqual(cache.parts[-3:-1], ("a3s-code", _bootstrap.__version__))
167
+ self.assertEqual(cache.name, _bootstrap._platform_tag())
112
168
 
113
169
  def test_xdg_cache_home_honored(self):
114
170
  os.environ["XDG_CACHE_HOME"] = "/tmp/xdg-test"
115
171
  cache = _bootstrap._cache_root()
116
- self.assertEqual(cache, Path(f"/tmp/xdg-test/a3s-code/{_bootstrap.__version__}"))
172
+ self.assertEqual(
173
+ cache,
174
+ Path(
175
+ f"/tmp/xdg-test/a3s-code/{_bootstrap.__version__}/"
176
+ f"{_bootstrap._platform_tag()}"
177
+ ),
178
+ )
117
179
 
118
180
  def test_explicit_override_wins(self):
119
181
  os.environ["XDG_CACHE_HOME"] = "/tmp/xdg-test"
120
182
  os.environ["A3S_CODE_CACHE_DIR"] = "/var/a3s-cache"
121
183
  cache = _bootstrap._cache_root()
122
- self.assertEqual(cache, Path(f"/var/a3s-cache/{_bootstrap.__version__}"))
184
+ self.assertEqual(
185
+ cache,
186
+ Path(
187
+ f"/var/a3s-cache/{_bootstrap.__version__}/"
188
+ f"{_bootstrap._platform_tag()}"
189
+ ),
190
+ )
123
191
 
124
192
 
125
193
  class ExtractNativeTests(unittest.TestCase):
@@ -141,11 +209,50 @@ class ExtractNativeTests(unittest.TestCase):
141
209
  _bootstrap._extract_native(buf.getvalue(), Path(tmp) / "pkg")
142
210
 
143
211
 
212
+ class CachedNativeSelectionTests(unittest.TestCase):
213
+ def test_selects_exact_interpreter_before_abi3(self):
214
+ with tempfile.TemporaryDirectory() as tmp:
215
+ cache = Path(tmp)
216
+ (cache / "_native.abi3.so").write_bytes(b"abi3")
217
+ (cache / "_native.cpython-312-darwin.so").write_bytes(b"exact")
218
+ with mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 12)):
219
+ selected = _bootstrap._find_cached_native(cache)
220
+ self.assertIsNotNone(selected)
221
+ self.assertEqual(selected.name, "_native.cpython-312-darwin.so")
222
+
223
+ def test_does_not_reuse_another_python_minor(self):
224
+ with tempfile.TemporaryDirectory() as tmp:
225
+ cache = Path(tmp)
226
+ (cache / "_native.cpython-313-darwin.so").write_bytes(b"wrong")
227
+ with mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 14)):
228
+ self.assertIsNone(_bootstrap._find_cached_native(cache))
229
+
230
+ def test_uses_abi3_when_exact_is_absent(self):
231
+ with tempfile.TemporaryDirectory() as tmp:
232
+ cache = Path(tmp)
233
+ (cache / "_native.abi3.so").write_bytes(b"abi3")
234
+ with mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 14)):
235
+ selected = _bootstrap._find_cached_native(cache)
236
+ self.assertIsNotNone(selected)
237
+ self.assertEqual(selected.name, "_native.abi3.so")
238
+
239
+
144
240
  class EnsureNativeLoadedTests(unittest.TestCase):
145
241
  def setUp(self):
146
242
  self._tmp = tempfile.mkdtemp(prefix="a3s-bootstrap-test-")
147
243
  self._prev_cache = os.environ.get("A3S_CODE_CACHE_DIR")
148
244
  os.environ["A3S_CODE_CACHE_DIR"] = self._tmp
245
+ # The product intentionally rejects CPython < 3.10. macOS ships a
246
+ # system Python 3.9 on some runners, though, and these tests exercise
247
+ # download/cache behavior rather than the version-floor error path.
248
+ # Run the fixture under a supported simulated minor in that case so
249
+ # the suite remains useful when invoked with the system interpreter.
250
+ self._supported_version_patch = None
251
+ if (sys.version_info.major, sys.version_info.minor) < _bootstrap._MIN_PYTHON:
252
+ self._supported_version_patch = mock.patch.object(
253
+ sys, "version_info", _FakeVersionInfo(3, 12)
254
+ )
255
+ self._supported_version_patch.start()
149
256
  # Reset the module-level latch so each test starts clean.
150
257
  _bootstrap._LOADED = False
151
258
 
@@ -154,6 +261,8 @@ class EnsureNativeLoadedTests(unittest.TestCase):
154
261
  os.environ.pop("A3S_CODE_CACHE_DIR", None)
155
262
  else:
156
263
  os.environ["A3S_CODE_CACHE_DIR"] = self._prev_cache
264
+ if self._supported_version_patch is not None:
265
+ self._supported_version_patch.stop()
157
266
  shutil.rmtree(self._tmp, ignore_errors=True)
158
267
  _bootstrap._LOADED = False
159
268
 
@@ -166,7 +275,7 @@ class EnsureNativeLoadedTests(unittest.TestCase):
166
275
  "version": "3.2.1",
167
276
  "assets": [
168
277
  {
169
- "filename": _bootstrap._wheel_filename("3.2.1"),
278
+ "filename": _bootstrap._wheel_candidates("3.2.1")[0],
170
279
  "sha256": expected_sha,
171
280
  }
172
281
  ],
@@ -186,12 +295,15 @@ class EnsureNativeLoadedTests(unittest.TestCase):
186
295
  ):
187
296
  cache = _bootstrap.ensure_native_loaded("3.2.1")
188
297
 
189
- # `_cache_root()` keys the cache dir on the module's own __version__,
190
- # not the version arg passed to `ensure_native_loaded`. Reference it
191
- # directly so this assertion can't go stale on a version bump (the
192
- # sibling CacheDirTests follow the same pattern).
193
- self.assertEqual(cache, Path(self._tmp) / _bootstrap.__version__)
194
- # Native file extracted at cache root, not under a subdirectory.
298
+ # `_cache_root()` keys the cache dir on the module's own version and
299
+ # current platform, not the version arg passed to `ensure_native_loaded`.
300
+ self.assertEqual(
301
+ cache,
302
+ Path(self._tmp)
303
+ / _bootstrap.__version__
304
+ / _bootstrap._platform_tag(),
305
+ )
306
+ # Native file is extracted directly into the platform-scoped cache.
195
307
  extracted = list(cache.glob("_native.*"))
196
308
  self.assertEqual(len(extracted), 1)
197
309
  register_mock.assert_called_once_with(extracted[0])
@@ -203,7 +315,7 @@ class EnsureNativeLoadedTests(unittest.TestCase):
203
315
  "version": "3.2.1",
204
316
  "assets": [
205
317
  {
206
- "filename": _bootstrap._wheel_filename("3.2.1"),
318
+ "filename": _bootstrap._wheel_candidates("3.2.1")[0],
207
319
  "sha256": "0" * 64,
208
320
  }
209
321
  ],
@@ -230,7 +342,7 @@ class EnsureNativeLoadedTests(unittest.TestCase):
230
342
  "version": "3.2.1",
231
343
  "assets": [
232
344
  {
233
- "filename": _bootstrap._wheel_filename("3.2.1"),
345
+ "filename": _bootstrap._wheel_candidates("3.2.1")[0],
234
346
  "sha256": "0" * 64,
235
347
  }
236
348
  ],
@@ -259,7 +371,7 @@ class EnsureNativeLoadedTests(unittest.TestCase):
259
371
  "version": "3.2.1",
260
372
  "assets": [
261
373
  {
262
- "filename": _bootstrap._wheel_filename("3.2.1"),
374
+ "filename": _bootstrap._wheel_candidates("3.2.1")[0],
263
375
  "sha256": hashlib.sha256(wheel_bytes).hexdigest(),
264
376
  }
265
377
  ],
@@ -284,6 +396,76 @@ class EnsureNativeLoadedTests(unittest.TestCase):
284
396
  self.assertEqual(call_count["n"], calls_after_first,
285
397
  "second call must not re-download")
286
398
 
399
+ def test_python314_selects_abi3_wheel(self):
400
+ wheel_bytes = _make_wheel()
401
+ with mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 14)):
402
+ abi3_name = _bootstrap._abi3_wheel_filename("3.2.1")
403
+ manifest = json.dumps(
404
+ {
405
+ "version": "3.2.1",
406
+ "assets": [
407
+ {
408
+ "filename": abi3_name,
409
+ "sha256": hashlib.sha256(wheel_bytes).hexdigest(),
410
+ }
411
+ ],
412
+ }
413
+ ).encode()
414
+
415
+ calls: list[str] = []
416
+
417
+ def fake_get(url: str) -> bytes:
418
+ calls.append(url)
419
+ if url.endswith("python-native-manifest.json"):
420
+ return manifest
421
+ return wheel_bytes
422
+
423
+ with (
424
+ mock.patch.object(_bootstrap, "_http_get", side_effect=fake_get),
425
+ mock.patch.object(_bootstrap, "_register_native") as register_mock,
426
+ ):
427
+ _bootstrap.ensure_native_loaded("3.2.1")
428
+
429
+ self.assertIn(abi3_name, calls[0])
430
+ register_mock.assert_called_once()
431
+
432
+ def test_python314_falls_back_to_exact_wheel_on_404(self):
433
+ wheel_bytes = _make_wheel()
434
+ with mock.patch.object(sys, "version_info", _FakeVersionInfo(3, 14)):
435
+ abi3_name = _bootstrap._abi3_wheel_filename("3.2.1")
436
+ exact_name = _bootstrap._wheel_filename("3.2.1")
437
+ manifest = json.dumps(
438
+ {
439
+ "version": "3.2.1",
440
+ "assets": [
441
+ {
442
+ "filename": exact_name,
443
+ "sha256": hashlib.sha256(wheel_bytes).hexdigest(),
444
+ }
445
+ ],
446
+ }
447
+ ).encode()
448
+
449
+ calls: list[str] = []
450
+
451
+ def fake_get(url: str) -> bytes:
452
+ calls.append(url)
453
+ if url.endswith("python-native-manifest.json"):
454
+ return manifest
455
+ if abi3_name in url:
456
+ raise _bootstrap.BootstrapHttpError(url, 404)
457
+ return wheel_bytes
458
+
459
+ with (
460
+ mock.patch.object(_bootstrap, "_http_get", side_effect=fake_get),
461
+ mock.patch.object(_bootstrap, "_register_native") as register_mock,
462
+ ):
463
+ _bootstrap.ensure_native_loaded("3.2.1")
464
+
465
+ self.assertIn(abi3_name, calls[0])
466
+ self.assertIn(exact_name, calls[1])
467
+ register_mock.assert_called_once()
468
+
287
469
 
288
470
  @unittest.skipUnless(
289
471
  os.environ.get("A3S_CODE_BOOTSTRAP_LIVE") == "1",
@@ -291,11 +473,12 @@ class EnsureNativeLoadedTests(unittest.TestCase):
291
473
  )
292
474
  class LiveDownloadTests(unittest.TestCase):
293
475
  def test_live_fetch_v3_2_0(self):
294
- # 3.2.0 has 12 wheels on GH Release — pick whichever matches the
295
- # current runner's platform/interpreter. Skip if the runner isn't
296
- # one of the supported triplets.
476
+ # 3.2.0 has native wheels on GH Release — pick whichever compatible
477
+ # asset is available for the current runner. Older releases predate
478
+ # the stable-ABI migration, so a newer interpreter may legitimately
479
+ # have no matching asset and should be reported as a skip.
297
480
  try:
298
- _bootstrap._wheel_filename("3.2.0")
481
+ _bootstrap._wheel_candidates("3.2.0")
299
482
  except _bootstrap.BootstrapError as exc:
300
483
  self.skipTest(str(exc))
301
484
  tmp = Path(tempfile.mkdtemp(prefix="a3s-live-"))
@@ -303,7 +486,10 @@ class LiveDownloadTests(unittest.TestCase):
303
486
  os.environ["A3S_CODE_CACHE_DIR"] = str(tmp)
304
487
  _bootstrap._LOADED = False
305
488
  with mock.patch.object(_bootstrap, "_register_native"):
306
- cache = _bootstrap.ensure_native_loaded("3.2.0")
489
+ try:
490
+ cache = _bootstrap.ensure_native_loaded("3.2.0")
491
+ except _bootstrap.BootstrapError as exc:
492
+ self.skipTest(str(exc))
307
493
  self.assertTrue(any(cache.glob("_native.*")))
308
494
  finally:
309
495
  os.environ.pop("A3S_CODE_CACHE_DIR", None)
a3s_code-8.0.1/PKG-INFO DELETED
@@ -1,64 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: a3s-code
3
- Version: 8.0.1
4
- Summary: A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases
5
- Author: A3S Lab
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/A3S-Lab/Code
8
- Project-URL: Repository, https://github.com/A3S-Lab/Code
9
- Project-URL: Issues, https://github.com/A3S-Lab/Code/issues
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: Implementation :: CPython
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Topic :: Software Development
15
- Requires-Python: >=3.10
16
- Description-Content-Type: text/markdown
17
-
18
- # a3s-code (Python bootstrap)
19
-
20
- `pip install a3s-code` ships this small pure-Python package. On first
21
- `import a3s_code` it downloads the native extension matching your
22
- interpreter and platform from the project's
23
- [GitHub Releases](https://github.com/A3S-Lab/Code/releases), verifies
24
- the wheel's sha256 against the release manifest, extracts the compiled
25
- extension into a per-user cache, and exposes the normal `a3s_code` API.
26
-
27
- Subsequent imports use the cached extension. Cache lives under
28
- `~/.cache/a3s-code/<version>/` (or `$XDG_CACHE_HOME/a3s-code/<version>/`).
29
-
30
- ## Why
31
-
32
- PyPI imposes a default 10 GB per-project storage cap. A Rust SDK with
33
- ~17 MB native wheels per Python × platform tripped that limit. GitHub
34
- Releases is the canonical wheel host; this bootstrap keeps
35
- `pip install a3s-code` working without dragging the native wheels back
36
- through PyPI.
37
-
38
- ## Supported platforms
39
-
40
- - macOS arm64 (Apple Silicon)
41
- - Linux x86_64 (glibc 2.28+)
42
- - Windows x86_64
43
-
44
- CPython 3.10, 3.11, 3.12, 3.13.
45
-
46
- ## Environment overrides
47
-
48
- | Variable | Effect |
49
- |---|---|
50
- | `A3S_CODE_CACHE_DIR` | Cache root (defaults to `$XDG_CACHE_HOME/a3s-code` or `~/.cache/a3s-code`) |
51
- | `A3S_CODE_RELEASES_BASE_URL` | Override the release base URL — useful for air-gapped mirrors |
52
- | `A3S_CODE_SKIP_HASH_CHECK` | `1` skips sha256 verification (do not use in production) |
53
-
54
- ## Manual install
55
-
56
- If you do not want the bootstrap to phone home, install the native
57
- wheel directly:
58
-
59
- ```bash
60
- pip install \
61
- 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp312-cp312-manylinux_2_28_x86_64.whl'
62
- ```
63
-
64
- Replace `<VERSION>` with the release to install, for example `6.4.0`.
a3s_code-8.0.1/README.md DELETED
@@ -1,47 +0,0 @@
1
- # a3s-code (Python bootstrap)
2
-
3
- `pip install a3s-code` ships this small pure-Python package. On first
4
- `import a3s_code` it downloads the native extension matching your
5
- interpreter and platform from the project's
6
- [GitHub Releases](https://github.com/A3S-Lab/Code/releases), verifies
7
- the wheel's sha256 against the release manifest, extracts the compiled
8
- extension into a per-user cache, and exposes the normal `a3s_code` API.
9
-
10
- Subsequent imports use the cached extension. Cache lives under
11
- `~/.cache/a3s-code/<version>/` (or `$XDG_CACHE_HOME/a3s-code/<version>/`).
12
-
13
- ## Why
14
-
15
- PyPI imposes a default 10 GB per-project storage cap. A Rust SDK with
16
- ~17 MB native wheels per Python × platform tripped that limit. GitHub
17
- Releases is the canonical wheel host; this bootstrap keeps
18
- `pip install a3s-code` working without dragging the native wheels back
19
- through PyPI.
20
-
21
- ## Supported platforms
22
-
23
- - macOS arm64 (Apple Silicon)
24
- - Linux x86_64 (glibc 2.28+)
25
- - Windows x86_64
26
-
27
- CPython 3.10, 3.11, 3.12, 3.13.
28
-
29
- ## Environment overrides
30
-
31
- | Variable | Effect |
32
- |---|---|
33
- | `A3S_CODE_CACHE_DIR` | Cache root (defaults to `$XDG_CACHE_HOME/a3s-code` or `~/.cache/a3s-code`) |
34
- | `A3S_CODE_RELEASES_BASE_URL` | Override the release base URL — useful for air-gapped mirrors |
35
- | `A3S_CODE_SKIP_HASH_CHECK` | `1` skips sha256 verification (do not use in production) |
36
-
37
- ## Manual install
38
-
39
- If you do not want the bootstrap to phone home, install the native
40
- wheel directly:
41
-
42
- ```bash
43
- pip install \
44
- 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp312-cp312-manylinux_2_28_x86_64.whl'
45
- ```
46
-
47
- Replace `<VERSION>` with the release to install, for example `6.4.0`.
@@ -1,64 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: a3s-code
3
- Version: 8.0.1
4
- Summary: A3S Code Python SDK — pure-Python bootstrap that fetches the native wheel from GitHub Releases
5
- Author: A3S Lab
6
- License: MIT
7
- Project-URL: Homepage, https://github.com/A3S-Lab/Code
8
- Project-URL: Repository, https://github.com/A3S-Lab/Code
9
- Project-URL: Issues, https://github.com/A3S-Lab/Code/issues
10
- Classifier: Programming Language :: Python :: 3
11
- Classifier: Programming Language :: Python :: Implementation :: CPython
12
- Classifier: License :: OSI Approved :: MIT License
13
- Classifier: Operating System :: OS Independent
14
- Classifier: Topic :: Software Development
15
- Requires-Python: >=3.10
16
- Description-Content-Type: text/markdown
17
-
18
- # a3s-code (Python bootstrap)
19
-
20
- `pip install a3s-code` ships this small pure-Python package. On first
21
- `import a3s_code` it downloads the native extension matching your
22
- interpreter and platform from the project's
23
- [GitHub Releases](https://github.com/A3S-Lab/Code/releases), verifies
24
- the wheel's sha256 against the release manifest, extracts the compiled
25
- extension into a per-user cache, and exposes the normal `a3s_code` API.
26
-
27
- Subsequent imports use the cached extension. Cache lives under
28
- `~/.cache/a3s-code/<version>/` (or `$XDG_CACHE_HOME/a3s-code/<version>/`).
29
-
30
- ## Why
31
-
32
- PyPI imposes a default 10 GB per-project storage cap. A Rust SDK with
33
- ~17 MB native wheels per Python × platform tripped that limit. GitHub
34
- Releases is the canonical wheel host; this bootstrap keeps
35
- `pip install a3s-code` working without dragging the native wheels back
36
- through PyPI.
37
-
38
- ## Supported platforms
39
-
40
- - macOS arm64 (Apple Silicon)
41
- - Linux x86_64 (glibc 2.28+)
42
- - Windows x86_64
43
-
44
- CPython 3.10, 3.11, 3.12, 3.13.
45
-
46
- ## Environment overrides
47
-
48
- | Variable | Effect |
49
- |---|---|
50
- | `A3S_CODE_CACHE_DIR` | Cache root (defaults to `$XDG_CACHE_HOME/a3s-code` or `~/.cache/a3s-code`) |
51
- | `A3S_CODE_RELEASES_BASE_URL` | Override the release base URL — useful for air-gapped mirrors |
52
- | `A3S_CODE_SKIP_HASH_CHECK` | `1` skips sha256 verification (do not use in production) |
53
-
54
- ## Manual install
55
-
56
- If you do not want the bootstrap to phone home, install the native
57
- wheel directly:
58
-
59
- ```bash
60
- pip install \
61
- 'https://github.com/A3S-Lab/Code/releases/download/v<VERSION>/a3s_code-<VERSION>-cp312-cp312-manylinux_2_28_x86_64.whl'
62
- ```
63
-
64
- Replace `<VERSION>` with the release to install, for example `6.4.0`.
File without changes
File without changes