Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
2b521e9
Added Build steps and Backward compatibility
bewithgaurav May 14, 2025
2791481
checked with main
bewithgaurav May 14, 2025
fc8f1f1
restored other files
bewithgaurav May 14, 2025
cb53741
restored another file
bewithgaurav May 14, 2025
eb8a8fc
changes for ddbc_bindings
bewithgaurav May 14, 2025
177b7c9
restoring requirements
bewithgaurav May 14, 2025
a6af0ad
tests updated with new build process
bewithgaurav May 14, 2025
2e52474
fixed pyd path for artifact
bewithgaurav May 14, 2025
24caa2d
added auth DLLs and upgraded to latest driver DLLs 18.5
bewithgaurav May 14, 2025
33ac184
test pipelines to store python arm64 libs as artifacts
bewithgaurav May 14, 2025
a906869
fixed arch
bewithgaurav May 15, 2025
06e63d9
debugging arch related things
bewithgaurav May 15, 2025
a39ce75
win arm whl fix
bewithgaurav May 15, 2025
024bad4
setuptools dependency
bewithgaurav May 15, 2025
606e3e4
import bdist_wheel from wheel
bewithgaurav May 15, 2025
c59afbe
version change for release
bewithgaurav May 15, 2025
2080911
fix loading path for mssql-auth DLL
bewithgaurav May 15, 2025
490a138
Merge branch 'main' of https://github.com/microsoft/mssql-python into…
bewithgaurav May 15, 2025
1a22912
store python_libs for arm64 as artifacts and remove unsupported archi…
bewithgaurav May 15, 2025
3e02f75
get python arm64 libs from previous successful run
bewithgaurav May 15, 2025
61981f0
remove all python arm64 libs
bewithgaurav May 15, 2025
54dcab1
fix pipeline format to download from latest branch run
bewithgaurav May 15, 2025
d9eedb1
remove artifacts etc. from test pipeline
bewithgaurav May 15, 2025
8019d72
clean out pyds directory - minimal now
bewithgaurav May 15, 2025
7471479
updated README
bewithgaurav May 15, 2025
a877e74
clean up a bunch of print statements
bewithgaurav May 15, 2025
e38887b
cleanup
bewithgaurav May 15, 2025
cce5341
cleanup for other archs
bewithgaurav May 15, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 22 additions & 8 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ mssql_python/pybind/build/

mssql_python/pybind/pymsbuild/build/

# Ignore all pyd files
**.pyd
# Ignore pyd file
mssql_python/ddbc_bindings.pyd

# Ignore pycache files and folders
__pycache__/
Expand All @@ -26,11 +26,25 @@ mssql_python/.vs
test-*.xml
**/test-**.xml

# Ignore coverage files
coverage.xml
.coverage
.coverage.*

# Ignore the build & mssql_python.egg-info directories
build/
mssql_python.egg-info/
mssql_python.egg-info/

# Python bytecode
__pycache__/
*.py[cod]
*$py.class

# Distribution / packaging
dist/
build/
*.egg-info/

# C extensions
*.so
*.pyd

# IDE files
.vscode/
.idea/
*.swp
164 changes: 164 additions & 0 deletions eng/pipelines/build-whl-pipeline.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Pipeline name shown in ADO UI
name: build-whl-pipeline

# Trigger the pipeline on pushes to these branches
trigger:
branches:
include:
- main
- dev

# Use Microsoft-hosted Windows VM
pool:
vmImage: 'windows-latest'

jobs:
- job: BuildPYDs
displayName: 'Build -'
# Strategy matrix to build all combinations
strategy:
matrix:
# Python 3.10 (only x64)
py310_x64:
pythonVersion: '3.10' # Host Python version
shortPyVer: '310' # Used in filenames like cp310
architecture: 'x64' # Host Python architecture
targetArch: 'x64' # Target architecture to pass to build.bat

# Python 3.11
py311_x64:
pythonVersion: '3.11' # Host Python version
shortPyVer: '311' # Used in filenames like cp311
architecture: 'x64' # Host Python architecture
targetArch: 'x64' # Target architecture to pass to build.bat
py311_arm64:
pythonVersion: '3.11'
shortPyVer: '311'
architecture: 'x64' # No arm64 Python, use x64 host
targetArch: 'arm64'

# Python 3.12
py312_x64:
pythonVersion: '3.12'
shortPyVer: '312'
architecture: 'x64'
targetArch: 'x64'
py312_arm64:
pythonVersion: '3.12'
shortPyVer: '312'
architecture: 'x64'
targetArch: 'arm64'

# Python 3.13
py313_x64:
pythonVersion: '3.13'
shortPyVer: '313'
architecture: 'x64'
targetArch: 'x64'
py313_arm64:
pythonVersion: '3.13'
shortPyVer: '313'
architecture: 'x64'
targetArch: 'arm64'

steps:
# Use correct Python version and architecture for the current job
- task: UsePythonVersion@0
inputs:
versionSpec: '$(pythonVersion)'
architecture: '$(architecture)'
addToPath: true
displayName: 'Use Python $(pythonVersion) ($(architecture))'

# Install required packages: pip, CMake, pybind11
- script: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install cmake pybind11
displayName: 'Install dependencies'

- task: DownloadPipelineArtifact@2
condition: eq(variables['targetArch'], 'arm64')
inputs:
buildType: 'specific'
project: '$(System.TeamProject)'
definition: 2134
buildVersionToDownload: 'latestFromBranch'
branchName: 'refs/heads/bewithgaurav/build_whl_pipeline' # Or 'refs/heads/dev'
artifactName: 'mssql-python-arm64-libs'
targetPath: '$(Build.SourcesDirectory)\mssql_python\pybind\python_libs\arm64'
displayName: 'Download ARM64 Python libs from latest successful run on branches'

# Build the PYD file by calling build.bat
- script: |
echo "Python Version: $(pythonVersion)"
echo "Short Tag: $(shortPyVer)"
echo "Architecture: Host=$(architecture), Target=$(targetArch)"

cd "$(Build.SourcesDirectory)\mssql_python\pybind"

REM Optional: override lib path if building for ARM64 since we cannot install arm64 python on x64 host
if "$(targetArch)"=="arm64" (
echo Using arm64-specific Python library...
set CUSTOM_PYTHON_LIB_DIR=$(Build.SourcesDirectory)\mssql_python\pybind\python_libs\arm64
)

REM Call build.bat to build the PYD file
call build.bat $(targetArch)

REM Calling keep_single_arch.bat to remove ODBC libs of other architectures
call keep_single_arch.bat $(targetArch)

cd ..\..
displayName: 'Build PYD for $(targetArch)'

# Copy the built .pyd file to staging folder for artifacts
- task: CopyFiles@2
inputs:
SourceFolder: '$(Build.SourcesDirectory)\mssql_python\pybind\build\$(targetArch)\py$(shortPyVer)\Release'
Contents: 'ddbc_bindings.cp$(shortPyVer)-*.pyd'
TargetFolder: '$(Build.ArtifactStagingDirectory)\all-pyds'
displayName: 'Place PYD file into artifacts directory'

# Build wheel package for the current architecture
- script: |
python -m pip install --upgrade pip
pip install wheel setuptools
set ARCHITECTURE=$(targetArch)
python setup.py bdist_wheel
displayName: 'Build wheel package for Python $(pythonVersion) ($(targetArch))'

# Copy the wheel file to the artifacts
- task: CopyFiles@2
inputs:
SourceFolder: '$(Build.SourcesDirectory)\dist'
Contents: '*.whl'
TargetFolder: '$(Build.ArtifactStagingDirectory)\dist'
displayName: 'Collect wheel package'

# Publish the collected .pyd file(s) as build artifacts
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\all-pyds'
ArtifactName: 'mssql-python-pyds'
publishLocation: 'Container'
displayName: 'Publish all PYDs as artifacts'

# Publish the python arm64 libraries as build artifacts for next builds if ARM64
- task: PublishBuildArtifacts@1
condition: eq(variables['targetArch'], 'arm64')
inputs:
PathtoPublish: '$(Build.SourcesDirectory)\mssql_python\pybind\python_libs\arm64'
ArtifactName: 'mssql-python-arm64-libs'
publishLocation: 'Container'
displayName: 'Publish arm64 libs as artifacts'

# Publish the collected wheel file(s) as build artifacts
- task: PublishBuildArtifacts@1
condition: succeededOrFailed()
inputs:
PathtoPublish: '$(Build.ArtifactStagingDirectory)\dist'
ArtifactName: 'mssql-python-wheels-dist'
publishLocation: 'Container'
displayName: 'Publish all wheels as artifacts'
8 changes: 2 additions & 6 deletions eng/pipelines/test-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,7 @@ jobs:

- script: |
cd mssql_python\pybind
mkdir build
cd build
cmake -DPython3_EXECUTABLE="python3" -DCMAKE_BUILD_TYPE=Debug ..
cmake --build . --config Debug
copy Debug\ddbc_bindings.pyd ..\..\ddbc_bindings.pyd
build.bat x64
displayName: 'Build .pyd file'

- script: |
Expand All @@ -51,7 +47,7 @@ jobs:

- task: PublishBuildArtifacts@1
inputs:
PathtoPublish: 'mssql_python/ddbc_bindings.pyd'
PathtoPublish: 'mssql_python/ddbc_bindings.cp313-amd64.pyd'
ArtifactName: 'ddbc_bindings'
publishLocation: 'Container'
displayName: 'Publish pyd file as artifact'
Expand Down
1 change: 0 additions & 1 deletion mssql_python/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ def _construct_connection_string(self, connection_str: str = "", **kwargs) -> st
else:
continue
conn_str += f"{key}={value};"
print(f"Connection string after adding driver: {conn_str}")

if ENABLE_LOGGING:
logger.info("Final connection string: %s", conn_str)
Expand Down
38 changes: 38 additions & 0 deletions mssql_python/ddbc_bindings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import os
import importlib.util
import sys
import platform

# Get current Python version and architecture
python_version = f"cp{sys.version_info.major}{sys.version_info.minor}"
if platform.machine().lower() in ('amd64', 'x86_64', 'x64'):
architecture = "amd64"
elif platform.machine().lower() in ('arm64', 'aarch64'):
architecture = "arm64"
else:
architecture = platform.machine().lower()

# Find the specifically matching PYD file
module_dir = os.path.dirname(__file__)
expected_pyd = f"ddbc_bindings.{python_version}-{architecture}.pyd"
pyd_path = os.path.join(module_dir, expected_pyd)

if not os.path.exists(pyd_path):
# Fallback to searching for any matching PYD if the specific one isn't found
pyd_files = [f for f in os.listdir(module_dir) if f.startswith('ddbc_bindings.') and f.endswith('.pyd')]
if not pyd_files:
raise ImportError(f"No ddbc_bindings PYD module found for {python_version}-{architecture}")
pyd_path = os.path.join(module_dir, pyd_files[0])
print(f"Warning: Using fallback PYD file {pyd_files[0]} instead of {expected_pyd}")

# Use the original module name 'ddbc_bindings' that the C extension was compiled with
name = "ddbc_bindings"
spec = importlib.util.spec_from_file_location(name, pyd_path)
module = importlib.util.module_from_spec(spec)
sys.modules[name] = module
spec.loader.exec_module(module)

# Copy all attributes from the loaded module to this module
for attr in dir(module):
if not attr.startswith('__'):
globals()[attr] = getattr(module, attr)
2 changes: 1 addition & 1 deletion mssql_python/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def add_driver_to_connection_str(connection_str):
# Insert the driver attribute at the beginning of the connection string
final_connection_attributes.insert(0, driver_name)
connection_str = ";".join(final_connection_attributes)
print(f"Connection string after adding driver: {connection_str}")

except Exception as e:
raise Exception(
"Invalid connection string, Please follow the format: "
Expand Down
Binary file added mssql_python/libs/x64/vcredist/msvcp140.dll
Binary file not shown.
Loading