Skip to content

Commit acdb42c

Browse files
jahnvi480bewithgauravCopilotsumitmsft
authored
FEAT: Add Python 3.15 Conda support (#839)
### Work Item / Issue Reference <!-- IMPORTANT: Please follow the PR template guidelines below. For mssql-python maintainers: Insert your ADO Work Item ID below For external contributors: Insert Github Issue number below Only one reference is required - either GitHub issue OR ADO Work Item. --> <!-- mssql-python maintainers: ADO Work Item --> > [AB#48877](https://sqlclientdrivers.visualstudio.com/c6d89619-62de-46a0-8b46-70b92a84d85e/_workitems/edit/48877) <!-- External contributors: GitHub Issue --> > GitHub Issue: N/A - related pull request linked below. ------------------------------------------------------------------- ### Summary <!-- Insert your summary of changes below. Minimum 10 characters required. --> Add ordinary CPython 3.15 to the existing combined binding/ODBC/RS Conda package without removing older supported versions. - Extend build and release defaults to 34 variants: Python 3.10-3.15 on five subdirs and 3.12-3.15 on win-arm64. Free-threaded Python and musllinux remain outside the Conda matrix. - Use the target Windows site-packages directory for extraction and validation: `lib/python/site-packages` on 3.15, retaining `Lib/site-packages` on older Python. - Pin conda-build 26.9.1 only for Windows legs containing 3.15, because it reads the target Python's recorded layout. Other legs retain the existing `<26` constraint. - Use `microsoft`, then `conda-forge`, for the win-arm64 3.15 build and verification dependencies. Preserve the exact older-version channel policies and the 3.12 ARM64 ABI workaround. Source RS/ODBC versions, optional dependencies, OS floors and publisher tools are unchanged. **User-directed PR smoke follow-up:** keep current-checkout source tests blocking, but obtain the real Linux CPython 3.11 smoke inputs directly from PyPI using `fetch-wheels --published-smoke`. Select PyPI's current published binding and its exact ODBC/RS dependencies, rather than unpublished source versions or independently mixing latest components. No smoke versions, filenames or SHA256 values are hardcoded. Downloads still require PyPI-provided hashes and actual METADATA/WHEEL/RECORD/dependency checks. Missing or mismatched inputs fail; no skip, older-release fallback or release-policy relaxation. The workflow supports both embedded-core and separate-RS published bindings without substituting source RS pins. This published packaging control does not qualify current-source RS or CPython 3.15. Production/default source-bound selection and trigger scoping are unchanged. The hardcoded digest literals reported by DevSkim have been removed, not suppressed. Builds on merged #817 and now targets `main`. **Validation** ```text .\myvenv\Scripts\python.exe -m pytest --noconftest -o addopts='' tests\test_027_conda_release_metadata.py tests\test_029_bundled_binary_audit.py tests\test_030_pe_machine_assert.py tests\test_033_driver_load_probe.py tests\test_034_conda_verify_cwd.py tests\test_035_conda_macho_assert.py tests\test_036_conda_provenance.py tests\test_037_rs_wheel_download.py tests\test_038_conda_archive_limits.py -q ``` Result: **1,388 passed** on the initial Conda support commit. These are source-only packaging/tooling tests, not native driver or SQL integration tests. ```text .\myvenv\Scripts\python.exe -m pytest --noconftest -o addopts='' tests\test_036_conda_provenance.py tests\test_027_conda_release_metadata.py tests\test_034_conda_verify_cwd.py -q ``` Result: **1,073 passed** on the PyPI-selection follow-up, covering explicit published/source selection, unavailable or invalid published dependencies, target restriction, embedded/separate RS and existing digest/dependency/provenance/trigger controls. Live `read_published_versions()` selected the current PyPI binding and its exact ODBC requirement successfully. Earlier local wheel-download attempts hit TLS handshake errors on Windows and a bounded Linux container; no TLS bypass was used. The normal post-push hosted `conda-audit` run validates actual wheel downloads and the build/audit for this revision. ```text .\myvenv\Scripts\python.exe -m pre_commit validate-config .\myvenv\Scripts\python.exe -m pre_commit run black-check --all-files --hook-stage pre-push git diff --check ``` Result: **all passed**. Normal commit and push hooks also passed. Earlier bounded local experiments solved the full ordinary-3.15 runtime dependency closure on all six subdirs. Synthetic packaging with actual Conda interpreters and conda-build 26.9.1 passed for win-64 3.10/3.15 and cross-built win-arm64 3.15, including ABI, PE and installed-component checks. **Not end-to-end qualification:** this host's `NoDefaultCurrentDirectoryInExePath` setting blocks conda-build's normal bare batch-file launch, including the production `build_packages` invocation. The synthetic packaging results used an explicit-path generated-batch launch followed by `conda-build --post`, without changing host policy or installed libraries. They do not establish normal pipeline success or native ARM64 execution. Approved-agent execution, real candidate wheels, native platform/SQL/TLS/authentication/bulk-copy and optional-feature qualification remain pending. No ADO pipeline was queued and nothing was published to Anaconda. <!-- ### PR Title Guide > For feature requests FEAT: (short-description) > For non-feature requests like test case updates, config updates , dependency updates etc CHORE: (short-description) > For Fix requests FIX: (short-description) > For doc update requests DOC: (short-description) > For Formatting, indentation, or styling update STYLE: (short-description) > For Refactor, without any feature changes REFACTOR: (short-description) > For performance improvements PERF: (short-description) > For AI tooling, agents, skills, prompts, or AI-assisted development workflows AI: (short-description) > For release related changes, without any feature changes RELEASE: #<RELEASE_VERSION> (short-description) ### Contribution Guidelines External contributors: - Create a GitHub issue first: https://github.com/microsoft/mssql-python/issues/new - Link the GitHub issue in the "GitHub Issue" section above - Follow the PR title format and provide a meaningful summary mssql-python maintainers: - Create an ADO Work Item following internal processes - Link the ADO Work Item in the "ADO Work Item" section above - Follow the PR title format and provide a meaningful summary --> --------- Co-authored-by: Gaurav Sharma <sharmag@microsoft.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Sumit Sarabhai <sumitsar@microsoft.com>
1 parent 2eb7929 commit acdb42c

19 files changed

Lines changed: 439 additions & 112 deletions

‎.github/workflows/conda-audit.yml‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,17 @@
33
#
44
# The OneBranch conda-build pipeline is `trigger: none` / `pr: none`, so its blocking
55
# audit never runs on a PR. This lightweight GitHub Actions job builds ONE real
6-
# linux-64 conda package from the SHIPPED PyPI wheels and runs
6+
# linux-64 conda package from the current published PyPI wheels and runs
77
# python -m eng.conda_tools elf on it, so a regression in the $ORIGIN climb,
88
# the declared conda deps (krb5/libtool/openssl), or the expected DT_NEEDED set fails
99
# the PR automatically -- the full-agent runtime masking cannot hide it.
1010
#
1111
# build.sh ALWAYS stamps the relative $ORIGIN climb onto the vendored Linux ODBC .so
1212
# (they are not code-signed, so the patch breaks no signature; an already-baked climb
1313
# is a byte-for-byte no-op). This gate builds one real linux-64 conda package from the
14-
# shipped PyPI wheels and audits the resulting climb (see conda/mssql-python/build.sh).
14+
# published wheels and audits the resulting climb (see conda/mssql-python/build.sh).
15+
# It is a published CPython 3.11 packaging control, not current-source RS/3.15
16+
# qualification; source-only tests above it remain current-checkout and blocking.
1517
#
1618
# PR triggers are conda-specific: general package/version changes and shared wheel
1719
# build infrastructure do not run this gate unless the PR also changes a path below.
@@ -72,15 +74,15 @@ jobs:
7274
tests/test_038_conda_archive_limits.py \
7375
tests/test_027_conda_release_metadata.py -q
7476
75-
- name: Fetch the shipped linux wheels from PyPI
77+
- name: Fetch the published CPython 3.11 smoke wheels from PyPI
7678
id: public-wheels
7779
working-directory: ${{ github.workspace }}
7880
run: |
7981
set -euo pipefail
80-
# Exact maintained release versions and PyPI digests, never an older/latest fallback.
81-
# Fetch RS only if binding METADATA requires it, using its distribution (not NuGet) pin.
82-
# Embedded-core public wheels are historical controls, not current-source RS proof.
82+
# Select PyPI's current binding and its exact ODBC/RS dependencies, not source pins.
83+
# Verify PyPI hashes and actual METADATA/WHEEL/RECORD; no older-release fallback.
8384
python -m eng.conda_tools fetch-wheels \
85+
--published-smoke \
8486
--wheel-dir "$PWD/wheels" --requirements-file "$PWD/wheel-inputs.txt" \
8587
--python-tag cp311 --conda-subdir linux-64
8688
echo "Downloaded:"; ls -1 wheels
@@ -91,10 +93,9 @@ jobs:
9193
RS_REQUIRED: ${{ steps.public-wheels.outputs.rsRequired }}
9294
run: |
9395
set -euo pipefail
94-
# The verified public dependency/ownership facts select the actual input set.
9596
rsArgs=()
9697
if [[ "$RS_REQUIRED" == "true" ]]; then
97-
rsArgs=(--rs-wheel-dir "$PWD/wheels" --rs-version-file "$PWD/eng/versions/mssql-python-rs.version")
98+
rsArgs=(--rs-wheel-dir "$PWD/wheels")
9899
elif [[ "$RS_REQUIRED" != "false" ]]; then
99100
echo "Missing verified public wheel profile"; exit 1
100101
fi

‎OneBranchPipelines/conda-build-pipeline.yml‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,11 @@ parameters:
3535
- 'Official'
3636
- 'NonOfficial'
3737
default: 'NonOfficial'
38-
# Python versions to build conda packages for (Windows loops these; the POSIX legs
39-
# auto-detect the same set from the downloaded wheels).
38+
# Ordinary CPython versions passed explicitly to the Windows and POSIX build legs.
4039
- name: pythonVersions
4140
displayName: 'Python versions (comma-separated)'
4241
type: string
43-
default: '3.10,3.11,3.12,3.13,3.14'
42+
default: '3.10,3.11,3.12,3.13,3.14,3.15'
4443
# H1: enable the minimal-base ldd reachability gate (CONDA_ASSERT_PREFIX_REACHABLE).
4544
# It fails CLOSED if the driver binds a system (or absent) krb5/gssapi/libltdl, so it
4645
# is only valid on a leg with NO system copies of those libs -- set true ONLY when
@@ -198,14 +197,14 @@ extends:
198197
# internally (so a broken/wrong-arch package is never staged), AND win-arm64 is in
199198
# the release gate's requiredSubdirs -- so a MISSING win-arm64 blocks the RELEASE.
200199
# Net: a win-arm64 failure isolates to win-arm64 (win-64 still ships) yet still
201-
# blocks the publish via the gate. DELIBERATELY a FIXED set (3.12-3.14), INDEPENDENT
200+
# blocks the publish via the gate. DELIBERATELY a FIXED set (3.12-3.15), INDEPENDENT
202201
# of the pythonVersions parameter: neither defaults nor conda-forge ships a
203202
# win-arm64 python for 3.10/3.11, so following the param would queue an unbuildable
204203
# 3.10/3.11 arm leg. Its own bld tree + subdir-scoped verify env keep it from
205204
# colliding with win-64 on this shared agent.
206205
- template: /OneBranchPipelines/steps/conda-build-validate-step.yml@self
207206
parameters:
208-
pythonVersion: '3.12,3.13,3.14'
207+
pythonVersion: '3.12,3.13,3.14,3.15'
209208
condaSubdir: 'win-arm64'
210209
condaTargetSubdir: 'win-arm64'
211210
odbcWheelDir: '$(Pipeline.Workspace)/odbc_wheels'

‎OneBranchPipelines/jobs/consolidate-conda-artifacts-job.yml‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
# Expected packages (validated conda subdirs). The self-contained mssql-python
1313
# package (which vendors the ODBC payload) is emitted per-Python by each build leg;
1414
# there is NO separate companion package:
15-
# win-64 : 5 py x mssql-python = 5
16-
# win-arm64 : 3 py x mssql-python (py3.12-3.14, cross-built on x64) = 3
17-
# osx-64 : 5 py x mssql-python (Intel Mac, native) = 5
18-
# osx-arm64 : 5 py x mssql-python (Intel Mac, cross-built) = 5
19-
# linux-64 : 5 py x mssql-python (glibc x86_64 host, native) = 5
20-
# linux-aarch64 : 5 py x mssql-python (x86_64 host + QEMU, best-effort) = 5
15+
# win-64 : 6 py x mssql-python (py3.10-3.15) = 6
16+
# win-arm64 : 4 py x mssql-python (py3.12-3.15, cross-built on x64) = 4
17+
# osx-64 : 6 py x mssql-python (Intel Mac, native) = 6
18+
# osx-arm64 : 6 py x mssql-python (Intel Mac, cross-built) = 6
19+
# linux-64 : 6 py x mssql-python (glibc x86_64 host, native) = 6
20+
# linux-aarch64 : 6 py x mssql-python (x86_64 host + QEMU, best-effort) = 6
2121
# ------------------------------------------------------------------------------
22-
# TOTAL (PyPI parity minus musllinux) = 28
23-
# win-arm64 is cross-built for py3.12-3.14 only (py3.10/3.11 have no win-arm64 deps
22+
# TOTAL (ordinary CPython, no musllinux or free-threaded variants) = 34
23+
# win-arm64 is cross-built for py3.12-3.15 only (py3.10/3.11 have no win-arm64 deps
2424
# on Anaconda defaults); its runtime import is skipped on the x64 host, so its arch
2525
# is enforced by the PE audit (eng.conda_tools pe). musllinux (no conda
2626
# musl subdir) is intentionally NOT conda-built. This job is BEST-EFFORT and never
@@ -117,7 +117,7 @@ jobs:
117117
n=$(find "$d" -type f \( -name '*.conda' -o -name '*.tar.bz2' \) | wc -l)
118118
printf ' %-14s %s\n' "$sub" "$n"
119119
done
120-
echo "Total conda package count: $PKG_COUNT (full PyPI-parity set = 28)"
120+
echo "Total conda package count: $PKG_COUNT (full ordinary-CPython set = 34)"
121121
122122
# BEST-EFFORT: never exit non-zero — an empty set emits a warning; a partial set
123123
# remains visible in the counts above. A conda hiccup must not block the wheel

‎OneBranchPipelines/steps/conda-build-validate-step.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
parameters:
2828
# Python version(s) to build, comma-separated X.Y (e.g. '3.13' or '3.12,3.13,3.14'); passed
2929
# straight to the orchestrator's --python-versions. win-64 follows the pythonVersions
30-
# parameter; win-arm64 uses a fixed 3.12-3.14 set (the singular name is kept for callers).
30+
# parameter; win-arm64 uses a fixed 3.12-3.15 set (the singular name is kept for callers).
3131
- name: pythonVersion
3232
type: string
3333
# Conda subdir for this leg's package metadata + staging: 'win-64' (native) or 'win-arm64'

‎OneBranchPipelines/steps/conda-publish-step.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ parameters:
6868
# against this job's independently downloaded artifact before upload.
6969
- name: pythonVersions
7070
type: string
71-
default: '3.10,3.11,3.12,3.13,3.14'
71+
default: '3.10,3.11,3.12,3.13,3.14,3.15'
7272
# The publisher hash lock targets CPython 3.12 / Windows x64; other runtimes reject.
7373
- name: pythonVersion
7474
type: string

‎OneBranchPipelines/steps/conda-release-step.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
# dependency solve PLUS a PE machine-type assert on the vendored arm64 .pyd/.dll, so a
3636
# broken or wrong-arch package is never STAGED. That build leg is continueOnError (so a
3737
# win-arm64 hiccup can't nuke the shared win-64 publish), and THIS release gate is where
38-
# win-arm64 is enforced: a missing win-arm64 fails the gate. Its matrix is 3.12-3.14 (the
38+
# win-arm64 is enforced: a missing win-arm64 fails the gate. Its matrix is 3.12-3.15 (the
3939
# gate's per-subdir override), since Anaconda `defaults` has no win-arm64 python for
4040
# 3.10/3.11. musllinux has no conda subdir at all (conda Linux is glibc-only), so absent.
4141
#
@@ -64,7 +64,7 @@ parameters:
6464
# subdir. The gate reads each binding's pyXY build tag from info/index.json.
6565
- name: pythonVersions
6666
type: string
67-
default: '3.10,3.11,3.12,3.13,3.14'
67+
default: '3.10,3.11,3.12,3.13,3.14,3.15'
6868
# Optional EXACT expected versions. When set, the gate asserts every package's
6969
# info/index.json version matches; when empty it still enforces one-version-per-
7070
# package consistency plus the subdir / matrix / pairing checks.

‎conda/README.md‎

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,15 @@ The `conda-audit` PR gate triggers only for `conda/`, `eng/conda_tools/`, Conda-
5757
OneBranch pipelines/steps/jobs, their native/probe/archive/provenance and release tests,
5858
and the workflow itself. General package metadata/version changes and shared wheel-build
5959
infrastructure do not trigger it on their own; mixed PRs with a Conda change still do.
60-
This scope does not change the unit-test runner, source-version wheel selection, or
61-
failure handling when a required wheel is unpublished.
60+
Source-only tests remain current-checkout and blocking. The real Linux CPython 3.11
61+
build/audit uses `fetch-wheels --published-smoke`: PyPI's current published binding
62+
and its exact ODBC dependency (plus RS when required). No smoke versions or hashes
63+
are hardcoded; downloads are verified against PyPI's SHA256 values and actual wheel
64+
metadata/ownership. Source release bumps do not select unpublished smoke inputs.
65+
The selected versions are logged and hash-required requirements are generated per run.
66+
Missing wheels, metadata/dependency or hash mismatches and build/audit failures still
67+
fail the gate; there is no skip or older-release fallback. This published packaging
68+
control does not qualify current-source RS or Python 3.15.
6269

6370
Run the source-only trigger regressions without a native build, SQL Server, or PyYAML:
6471

@@ -112,8 +119,9 @@ macOS retains its external Homebrew/MacPorts OpenSSL prerequisite for encryption
112119
Conda OpenSSL alone does not satisfy the driver's system-path lookup.
113120

114121
The release goal is the matching PyPI release's public API and supported feature
115-
behavior on all 28 ordinary CPython variants: 3.10-3.14 on win-64, linux-64,
116-
linux-aarch64, osx-64 and osx-arm64; 3.12-3.14 on win-arm64. No silent removal of
122+
behavior on all 34 ordinary CPython variants: 3.10-3.15 on win-64, linux-64,
123+
linux-aarch64, osx-64 and osx-arm64; 3.12-3.15 on win-arm64. Free-threaded CPython
124+
(including `cp315t`) and musllinux are not Conda targets. No silent removal of
117125
required native functionality is acceptable. Optional features require their
118126
corresponding dependencies; Windows ARM64 PyArrow availability remains a blocker
119127
to qualifying those features, not permission to drop them.
@@ -125,7 +133,7 @@ load do not establish those results. Applicable OS, certificate and authenticati
125133
configuration remain external prerequisites.
126134

127135
Use only organizationally approved channels and handle applicable terms separately;
128-
the Windows ARM64 dependency profile includes Anaconda `defaults`. Before unattended
136+
the Windows ARM64 3.12-3.14 dependency profile includes Anaconda `defaults`. Before unattended
129137
Windows ARM64 builds, agent owners must use approved provisioning to put a disposable
130138
Conda installation on `PATH`, with applicable channel terms handled for the job's
131139
execution identity. The orchestrator's automatic Miniforge installation does not
@@ -134,6 +142,25 @@ or verification solve stops with Conda's diagnostic; provision the prerequisite
134142
running again. Automatic acceptance, including an inherited
135143
`CONDA_PLUGINS_AUTO_ACCEPT_TOS` opt-in, remains disabled.
136144

145+
Windows ARM64 3.15 uses `microsoft`, then `conda-forge`, for both build and verification
146+
(after the local verification channel), without `defaults`. Older targets retain their
147+
existing channel policies and the ARM64 3.12 manual ABI pin. The blocking full dependency
148+
solve remains; every 3.15 package must pass the `python_abi 3.15.* *_cp315` native audit.
149+
150+
### Python 3.15 packaging
151+
152+
Conda-forge's Windows Python 3.15 declares `lib/python/site-packages` instead of
153+
`Lib/site-packages` ([layout change](https://conda-forge.org/blog/2026/09/03/python-315/)).
154+
The Windows recipe uses the target's `SP_DIR` for binding/RS/ODBC extraction, with
155+
matching native and installed-metadata checks. Windows legs containing 3.15 use
156+
**conda-build 26.9.1** for all requested variants: its
157+
[26.9.0 fix](https://github.com/conda/conda-build/releases/tag/26.9.0) reads
158+
`python_site_packages_path` from the target Python record, including cross builds.
159+
25.x computes the old Windows path even for 3.15. Other legs retain `conda-build<26`;
160+
the publishing toolchain is unchanged. The existing RS 0.3.0 stable-ABI selection and
161+
ODBC `py3-none` wheels need no version change. PyArrow stays optional; no speculative
162+
`libpython` dependency or change to the Unix OS floors is introduced.
163+
137164
Run this existing build workflow only in a disposable isolated installation: shared-environment
138165
ownership hardening is outside this change. Publication/provenance tooling is included
139166
alongside this native/tooling foundation; see the
@@ -262,17 +289,19 @@ members. This detects unowned or cross-owned additions; it cannot recover file o
262289
after an overwrite of an already owned path, which is why the raw pre-extraction gate
263290
is required.
264291

265-
`fetch-wheels` uses exact current maintained versions, hash-required binary-only PyPI
292+
By default, `fetch-wheels` uses exact current maintained versions, hash-required binary-only PyPI
266293
downloads, and actual wheel metadata/ownership. Pip selects for its executing interpreter;
267294
the requested Python/platform must match the binding, ODBC and selected RS wheel tags
268295
before the command accepts the inputs. These arguments validate the download, rather
269296
than enabling cross-target pip resolution. An authentic published embedded-core
270297
binding is explicitly reported as a **historical published packaging control, not
271298
current-source RS qualification**. An RS-dependent published binding requires its exact
272-
provider and source pin; unavailable releases, malformed declarations, or mismatches
299+
provider and selected pin; unavailable releases, malformed declarations, or mismatches
273300
fail with no older-version or TLS fallback. Public availability does not gate the
274301
recorded ADO artifact path. Neither a public input check nor static archive checks
275302
establish installed SQL/runtime qualification.
303+
Only the explicit `--published-smoke` option selects the published inputs above;
304+
production, provenance, preflight and release/publish version selection are unchanged.
276305

277306
The driver-load probe's sole implementation is
278307
`eng/conda_tools/driver_load_probe.py`. It separates native connection execution,

‎conda/mssql-python/bld.bat‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@ REM vendor the ODBC Driver 18 payload inside it. conda-build exports PKG_NAME /
44
REM PKG_VERSION / CONDA_PY; the pipeline exports WHEELS_DIR + MSSQL_ODBC_VERSION.
55
setlocal enabledelayedexpansion
66

7-
set "SP=%PREFIX%\Lib\site-packages"
7+
REM conda-build 26.9+ reads the target Python's python_site_packages_path (CFEP-27).
8+
REM Python 3.15 uses lib\python\site-packages; older Windows targets use Lib\site-packages.
9+
if not defined SP_DIR (
10+
echo ERROR: conda-build must supply the target Python site-packages in SP_DIR.
11+
exit /b 1
12+
)
13+
set "SP=%SP_DIR%"
814
if not exist "%SP%" mkdir "%SP%"
915
set "PKG_UNDERSCORE=%PKG_NAME:-=_%"
1016

‎conda/mssql-python/meta.yaml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ requirements:
3636
# --python matrix here, so each build emits the matching py3XX package. A range such
3737
# as `python >=3.10` collapses ALL --python builds into ONE cp<newest> package (build
3838
# string "py>=310") whose python_abi is pinned to 3.14, so `conda create python=3.10
39-
# mssql-python` can't solve. The >=3.10 floor is enforced implicitly: only py310-py314
39+
# mssql-python` can't solve. The >=3.10 floor is enforced implicitly: only py310-py315
4040
# are built and each package's python_abi pins its exact minor.
4141
- python
4242
- pip

‎eng/conda_tools/build.py‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,10 @@ def build_packages(
302302
croot = os.path.join(os.path.dirname(os.path.abspath(bld)), "croot")
303303
if os.path.isdir(croot):
304304
shutil.rmtree(croot)
305-
channels = ["microsoft", "conda-forge"]
306-
if target_subdir == "win-arm64":
307-
channels.insert(0, "defaults")
308305
for py in pyvers:
306+
channels = ["microsoft", "conda-forge"]
307+
if target_subdir == "win-arm64" and py != "3.15":
308+
channels.insert(0, "defaults")
309309
environment._log(
310310
f"=== [py {py}] build mssql-python (self-contained: vendors the ODBC payload) ==="
311311
)
@@ -471,8 +471,8 @@ def execute(args: argparse.Namespace) -> int:
471471
conda = environment.find_or_install_conda(output_dir)
472472
environment._log(f"Using conda: {conda}")
473473
environment.run([conda, "--version"], what="conda --version")
474-
builder = environment.create_builder_env(conda)
475474
pyvers = detect_pythons(links, python_versions)
475+
builder = environment.create_builder_env(conda, target, pyvers)
476476
cross_build = bool(args.conda_target_subdir)
477477
env = environment.build_env(mssql_ver, odbc_ver, links, args.conda_target_subdir, rs_ver)
478478

0 commit comments

Comments
 (0)