This recipe combines matching binding, ODBC and RS wheels into one mssql-python
Conda package. The RS distribution owns the required mssql_py_core package and
its private native libraries; the binding wheel must not own them. Pip installs
mssql-python-odbc and mssql-python-rs as separate companion distributions.
Neither installation requires a separately installed ODBC driver or driver manager.
For consolidated wheel artifacts, the builder first selects bindings matching the
effective target platform and --python-versions (or auto-detects versions from
target-compatible bindings). Other Python/platform inputs are ignored before metadata
and RS dependency checks. Selected inputs still require matching versions, ownership,
tags and native compatibility; missing required RS wheels remain fatal.
The builder validates raw wheel core ownership before staging or recipe extraction,
including unrecorded files and wheel spread-path/case aliases. ODBC never supplies
mssql_py_core; the selected RS provider (or historical binding) must own every core
file in RECORD. Direct recipe callers must use these validated wheel inputs.
Public and staged wheels also require one canonical root METADATA member, with no
extra nested or aliased metadata. Package audits require binding metadata and exactly
one RECORD for each installed distribution; missing or duplicate ownership records fail.
Low-level binary-format parsers remain independent of package metadata.
These checks inspect all actual METADATA/RECORD/WHEEL candidates before accepting
installed ownership, including case, backslash and normalized-path aliases that a
canonical-only metadata collector would omit. Aliased or orphan entries are rejected,
not normalized into an accepted package.
Archive readers stream ZIP components through the selected zstandard backend (or
stream legacy .tar.bz2 files) instead of materializing complete TAR components.
Individual files still return bounded byte buffers for the native parsers. Fixed
limits fail explicitly; there is no command-line or environment override:
| Processing budget | Limit |
|---|---|
| Archive file / ZIP component bytes | 256 MiB |
| ZIP central-directory read / ZIP entries | 1 MiB / 10,000 |
| Expanded TAR stream, including padding | 1 GiB |
| Cumulative TAR member bytes | 512 MiB |
| Individual member / metadata member bytes | 128 MiB / 8 MiB |
| Cumulative TAR metadata / TAR headers | 64 MiB / 10,000 |
| Zstandard decoder window / frames per component | 64 MiB / 10,000 |
Checks apply before member allocation and while consuming 64 KiB chunks, including frames without a declared expanded size. The third-party zstandard reader also receives a bounded frame-structure pass because its streaming API alone accepts truncated frame endings. ZIP envelopes must use stored or deflate compression; sparse TAR extensions are rejected before sparse-map processing. Wheel metadata reads share the ZIP and metadata budgets. These are package-reader limits, not a claim that NuGet transport downloads or total process memory have the same bounds.
The GitHub audit job installs its complete Linux x64 / CPython 3.11 test-tool closure
from requirements-audit.txt with --require-hashes --only-binary=:all:.
requirements-audit.in records the reviewed direct pins and regeneration commands.
This audit-only lock is separate from the Windows publisher lock; it does not pin
the hosted runner image or every input to the later Conda build.
Direct recipe builds must set MSSQL_PYTHON_VERSION to the exact selected code-wheel
version before rendering/building. The shared orchestrator derives and supplies it
automatically; omitted input fails recipe rendering instead of choosing a release.
Both native installation and cross extraction require the bulk-copy initializer and
a compatible extension filename. The separate native audits still validate binary headers.
For RS-dependent bindings, the orchestrator also supplies the derived MSSQL_RS_VERSION
and a validated rs-wheel-cp<minor>.txt selection in WHEELS_DIR. Recipes install or
extract that entire wheel, including private libraries and distribution metadata, before
checking the required core. The selection also supports compatible stable-ABI wheels
without retagging them or executing a cross-target interpreter.
The same selection bytes are retained inside the installed RS .dist-info directory
as conda-wheel-source.txt: one wheel basename followed by a newline. This identifies
the raw wheel entry in the producer transport receipt; it does not equate raw-wheel
hashes with the final Conda archive hash after Linux relocation.
Use build --rs-wheel-dir <producer-artifact>/rs-wheels --rs-version-file <producer-artifact>/dist/mssql-python-rs.version for RS inputs.
The version file asserts the selected producer's source contract, not a new release-version
setting. The distinct NuGet transport pin remains in mssql-python-rs-nuget.version;
the downloader records its content hash and individual wheel hashes in transport.json.
Conda consumers use staged producer bytes, not a fresh download using their checkout's pin.
Published historical bindings that declare no RS dependency are accepted only when their payload and RECORD own the core initializer and native extension. They produce an explicit historical embedded-core / NOT current-source RS qualification diagnostic. A supplied RS source assertion, malformed RS declaration, or missing required RS wheel cannot fall back to that profile. Equal binding version strings do not establish equal payload contracts.
This is a temporary candidate, not an announcement of public channel availability. Obtain the exact candidate archive/channel from its owner and install into a new Conda environment. Activate it and select the same interpreter/kernel in your IDE or notebook. Application imports and the public API remain unchanged. Use Conda for upgrades; do not overwrite Conda-owned driver files with pip.
Linux requires glibc >=2.34 for the complete native payload, including the
bulk-copy core, even when the binding wheel has a lower platform tag. Do not force
installation on older glibc. This does not change the separate PyPI support claim.
The current RS transport's manylinux_2_34 inputs link OpenSSL 3 and match the existing
openssl >=3,<4 dependency; its manylinux_2_28 inputs link incompatible OpenSSL 1.1.
The RS core and private Linux driver receive their own exact relative RPATH climbs to
the environment's lib directory. They are not ODBC Driver 18 distro trees and are not
deduplicated with the separate ODBC wheel's payload.
macOS retains its external Homebrew/MacPorts OpenSSL prerequisite for encryption;
Conda OpenSSL alone does not satisfy the driver's system-path lookup.
The release goal is the matching PyPI release's public API and supported feature behavior on all 28 ordinary CPython variants: 3.10-3.14 on win-64, linux-64, linux-aarch64, osx-64 and osx-arm64; 3.12-3.14 on win-arm64. No silent removal of required native functionality is acceptable. Optional features require their corresponding dependencies; Windows ARM64 PyArrow availability remains a blocker to qualifying those features, not permission to drop them.
These guards are not full-matrix parity certification. Native target execution, SQL, certificate-verified TLS, authentication, bulk-copy and optional-feature tests remain required before release. Cross-build/static checks and a DB-less driver load do not establish those results. Applicable OS, certificate and authentication configuration remain external prerequisites.
Use only organizationally approved channels and handle applicable terms separately;
the Windows ARM64 dependency profile includes Anaconda defaults. Before unattended
Windows ARM64 builds, agent owners must use approved provisioning to put a disposable
Conda installation on PATH, with applicable channel terms handled for the job's
execution identity. The orchestrator's automatic Miniforge installation does not
establish that approval. If Conda enforces terms that have not been handled, the build
or verification solve stops with Conda's diagnostic; provision the prerequisite before
running again. Automatic acceptance, including an inherited
CONDA_PLUGINS_AUTO_ACCEPT_TOS opt-in, remains disabled.
Run this existing build workflow only in a disposable isolated installation: shared-environment ownership hardening is outside this change. Publication/provenance tooling is included alongside this native/tooling foundation; see the release status and qualification caveats. Neither this native-packaging change nor validate-only success authorizes production publication.
The internal eng/conda_tools package separates archive I/O (archive.py), native
compatibility policy (contracts.py), binary facts (formats/elf.py, pe.py, and
macho.py), and the shared audit lifecycle (audit.py). Command arguments and
human-readable reporting live in __main__.py. Conda provisioning and process
execution live in environment.py; build.py sequences wheel selection, building,
auditing and staging; verify.py keeps installed-package probes isolated.
Release matrix and Python-admissibility policy live in release.py, recorded
Azure DevOps source checks in provenance.py, source-bound component inputs and
public wheel fetching in inputs.py, and staged publication/recovery in publication.py. Both release
and native auditing use archive.py; release validation retains its stricter
container and index rules rather than weakening them to the generic audit policy.
Each .conda component reader requires exactly one matching info-*.tar.zst or
pkg-*.tar.zst entry. Missing components and additional matches, including duplicate
ZIP entries with the same name, are rejected before decompression.
Run the module commands from the repository root, followed by the existing build or audit arguments:
python -m eng.conda_tools build --help
python -m eng.conda_tools elf --root <package-directory>
python -m eng.conda_tools pe --root <package-directory> --subdir win-arm64
python -m eng.conda_tools macho --root <package-directory> --subdir osx-arm64
python -m eng.conda_tools validate --root <package-directory>
python -m eng.conda_tools provenance
python -m eng.conda_tools promote --help
python -m eng.conda_tools fetch-wheels --help
python -m eng.conda_tools probe-driver
These replace the old standalone audit, build, and release scripts. They require the source
checkout; the internal tools are not installed in the driver wheel. If Python
reports No module named 'eng', run from the checkout root rather than an installed
driver environment. Build callers set the tooling subprocess's working directory
explicitly, without changing PYTHONPATH or the parent working directory.
Static audits do not import the driver. Runtime verification remains in separate
processes from a neutral working directory, with the required core loaded
independently before API probes.
provenance uses the existing release pipeline environment and read-only job-token
access. promote --check-local-only needs neither a publishing token nor an
Anaconda client; actual publication and recovery require restricted credentials and
the shared protected release stage described below. Module placement is not a new
authorization boundary. The PowerShell upload process deadlines, attempted-file
tracking, process-tree termination, and dry-run plan remain in their pipeline tasks.
Network publication and recovery require an explicit nonblank ANACONDA_API_TOKEN,
not an ambient or cached login. The publishing task removes BINSTAR_API_TOKEN
only from its process and children so the CLI uploader uses the same reviewed credential.
User/machine environment settings and saved credentials are not modified.
Only trusted, reviewed release revisions may be queued, including validate-only feature
branches: their YAML and Python run with System.AccessToken. YAML provenance checks
cannot sandbox an untrusted queued revision or protect that token from it. Administrators
must restrict pipeline editing/queueing and source access, minimize the job identity's
permissions, and separately protect publishing credentials. A dry run omits the publishing
credential group; it is not token-free execution.
Before authorizing production use of Anaconda Publishing, its resource owner must
configure an ADO Branch control check
on that variable group in Pipelines > Library > Approvals and checks:
allow only refs/heads/main, require branch protection, and fail when protection
cannot be verified. This resource-side check applies to every consuming stage and
pipeline, including the branches of linked producer runs; feature-branch publication
must fail before the stage receives the publishing credential. Preserve existing
permissions and approvals, and restrict permission to administer or bypass the check.
Do not grant broader pipeline access as part of configuring it.
The existing publishToConda condition omits this group for validate-only runs, so
trusted feature-branch validation remains separate from credentialed publication.
Neither a checkout-local branch check nor a secondary pinned checkout can replace
the resource-side control: editable YAML could bypass either. These external checks
are not installed by this repository; production must remain unapproved until the
resource owner verifies their configuration and enforcement. Branch control does
not provide the separate exclusive publication lock.
The resource owner must also enable the native Exclusive lock check on the same
Anaconda Publishing variable group. Production selects lockBehavior: sequential
on the enclosing CondaRelease stage; this setting orders waiting runs but does not
create the external check. The lock spans validation, staged uploads, the initial
label snapshot, promotion, rollback and staging cleanup until the stage ends.
All publishers and recovery paths for microsoft/mssql-python must consume that
same resource, across versions and target labels; separate groups would not serialize
them. Keep the group and lock behavior absent from validate-only runs.
Recover by rerunning the original protected release stage with its original artifact
inputs, preserving the build-specific staging label and reacquiring the shared lock.
Do not run mutating promote or --cleanup-staging commands outside that protected
stage: the Python helpers do not acquire an ADO resource lock themselves.
After uncertain writer termination, first confirm the writer has stopped; a native
lock does not terminate orphaned processes or repair interrupted remote operations.
Inspect check configuration and compiled stage wiring separately from run-time lock
acquisition; configuration readback alone is not evidence that a run holds the lock.
The release pipeline resolves AUTO from the recorded upstream wheel commit, not the release checkout or a latest-version lookup. It cross-checks binding setup/runtime versions and reads ODBC and, when explicitly required by that source, RS distribution versions. RS's NuGet transport pin is separate. Missing or ambiguous source declarations fail rather than select a historical profile. A supplied binding version is only an assertion against this resolved version.
Both readiness and the credentialed job use validate --release-versions to read the
verified RELEASE_VERSIONS JSON from the environment; RS_TRANSPORT_VERSION supplies
the separate transport assertion. This avoids passing JSON quoting or empty arguments
through Windows PowerShell. Explicit JSON may also follow --release-versions in
source-only controls. With this flag, absent versions fail closed. Without it, validate
remains the metadata/matrix-only inspection command and makes no source-input claim.
The source-bound gate checks each installed component's METADATA and RECORD ownership,
the binding's exact dependency pins, and the selected RS filename/WHEEL tags against
rs-transport.json. Raw wheel/transport hashes remain input evidence; relocated
installed native files are checked by the native audits, not falsely compared with raw
wheel hashes. No numeric RS build ID is inferred from a transport-version suffix.
Release and native auditing also check all installed core paths, not only RECORD-filtered
members. This detects unowned or cross-owned additions; it cannot recover file origin
after an overwrite of an already owned path, which is why the raw pre-extraction gate
is required.
fetch-wheels uses exact current maintained versions, hash-required binary-only PyPI
downloads, and actual wheel metadata/ownership. Pip selects for its executing interpreter;
the requested Python/platform must match the binding, ODBC and selected RS wheel tags
before the command accepts the inputs. These arguments validate the download, rather
than enabling cross-target pip resolution. An authentic published embedded-core
binding is explicitly reported as a historical published packaging control, not
current-source RS qualification. An RS-dependent published binding requires its exact
provider and source pin; unavailable releases, malformed declarations, or mismatches
fail with no older-version or TLS fallback. Public availability does not gate the
recorded ADO artifact path. Neither a public input check nor static archive checks
establish installed SQL/runtime qualification.
The driver-load probe's sole implementation is
eng/conda_tools/driver_load_probe.py. It separates native connection execution,
pure outcome classification and command reporting with typed interfaces.
Verification runs that file by absolute path with the target environment's Python.
Its standard-library-only bootstrap does not require eng to be installed there,
so the tooling namespace does not weaken installed-package isolation.
The probe-driver module command is a convenience diagnostic in the calling
interpreter, not a substitute for this neutral-directory installed-package check.
The files remaining under conda/ are the conventional recipe entrypoints,
metadata, documentation and line-ending configuration. Shared NuGet transport,
feed-resolution and output-safety utilities remain under eng/scripts because
non-Conda native build/development workflows also use them; Conda reuses those
implementations rather than keeping private copies.