Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
60 changes: 60 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
# Use Python 3.14 with Debian Bookworm as the base image
FROM mcr.microsoft.com/devcontainers/python:3.14-bookworm

# Set environment variables
ENV DEBIAN_FRONTEND=noninteractive
ENV PYTHONPATH=/workspaces/mssql-python
ENV CMAKE_BUILD_TYPE=Debug

# Set timezone (configurable via build arg)
ARG TZ=UTC
ENV TZ=$TZ
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
&& echo $TZ > /etc/timezone

# Install all system dependencies in one layer
RUN apt-get update && apt-get install -y \
# Build tools
build-essential \
cmake \
pkg-config \
ninja-build \
python3-dev \
pybind11-dev \
# ODBC prerequisites (unixodbc-dev provides sql.h headers for compilation)
unixodbc-dev \
gnupg \
software-properties-common \
# Utilities
curl \
wget \
git \
vim \
nano \
htop \
tree \
jq \
# Clean up
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Install Microsoft ODBC Driver for SQL Server
RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg \
&& echo "deb [arch=arm64,amd64 signed-by=/usr/share/keyrings/microsoft-prod.gpg] https://packages.microsoft.com/debian/12/prod bookworm main" > /etc/apt/sources.list.d/mssql-release.list \
&& apt-get update \
&& ACCEPT_EULA=Y apt-get install -y msodbcsql18 \
&& ACCEPT_EULA=Y apt-get install -y mssql-tools18 \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*

# Add mssql-tools to PATH
ENV PATH="$PATH:/opt/mssql-tools18/bin"

# Set the default user to vscode (created by the base image)
USER vscode

# Set the working directory
WORKDIR /workspaces/mssql-python

# Default command
CMD ["/bin/bash"]
73 changes: 73 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"name": "MSSQL Python Driver",
"build": {
"dockerfile": "Dockerfile",
"context": "."
},
"customizations": {
"vscode": {
"settings": {
"python.defaultInterpreterPath": "/usr/local/bin/python",
"python.terminal.activateEnvironment": false,
"editor.formatOnSave": true,
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
"cmake.configureOnOpen": false,
"cmake.configureOnEdit": false,
"cmake.automaticReconfigure": false,
"files.exclude": {
"**/__pycache__": true,
"**/*.pyc": true,
"**/.pytest_cache": true,
"**/build": true
}
},
"extensions": [
"ms-python.python",
"ms-python.vscode-pylance",
"ms-python.pylint",
"ms-python.black-formatter",
"ms-toolsai.jupyter",
"ms-vscode.cmake-tools",
"ms-vscode.cpptools",
"ms-vscode.cpptools-extension-pack",
"github.copilot",
"github.copilot-chat",
"ms-vscode.test-adapter-converter",
"littlefoxteam.vscode-python-test-adapter",
"ms-azuretools.vscode-docker",
"ms-mssql.mssql"
]
}
},
"features": {
"ghcr.io/devcontainers/features/git:1": {},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
"ghcr.io/devcontainers/features/common-utils:2": {
"installZsh": true,
"configureZshAsDefaultShell": true,
"installOhMyZsh": true,
"upgradePackages": true,
"username": "vscode",
"userUid": "automatic",
"userGid": "automatic"
}
},
"forwardPorts": [1433],
"portsAttributes": {
"1433": {
"label": "SQL Server",
"onAutoForward": "notify"
}
},
"postCreateCommand": "bash .devcontainer/post-create.sh",
"remoteUser": "vscode",
"containerEnv": {
"PYTHONPATH": "/workspaces/mssql-python",
"CMAKE_BUILD_TYPE": "Debug"
},
"workspaceMount": "source=${localWorkspaceFolder},target=/workspaces/mssql-python,type=bind,consistency=cached",
"workspaceFolder": "/workspaces/mssql-python"
}
115 changes: 115 additions & 0 deletions .devcontainer/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
#!/bin/bash

# Post-create script for MSSQL Python Driver devcontainer
set -e

echo "🚀 Setting up MSSQL Python Driver development environment..."

# Install Python packages from requirements.txt
echo "📦 Installing Python packages..."
pip install --upgrade pip setuptools wheel
pip install -r requirements.txt

# Create symlink for 'python' command (build.sh expects it)
echo "🔗 Creating python symlink..."
sudo ln -sf $(which python3) /usr/local/bin/python

# Set up useful shell aliases (for both bash and zsh)
echo "⚡ Setting up aliases..."
cat > ~/.shell_aliases << 'EOF'
# MSSQL Python Driver development aliases
alias build='cd /workspaces/mssql-python/mssql_python/pybind && ./build.sh && cd /workspaces/mssql-python'
alias test='python -m pytest -v'
EOF

# Ensure aliases are sourced in both shells
grep -qxF 'source ~/.shell_aliases' ~/.bashrc 2>/dev/null || echo 'source ~/.shell_aliases' >> ~/.bashrc
grep -qxF 'source ~/.shell_aliases' ~/.zshrc 2>/dev/null || echo 'source ~/.shell_aliases' >> ~/.zshrc

# Verify environment
echo ""
echo "🔍 Verifying environment..."
python --version
pip --version
cmake --version
if command -v sqlcmd &> /dev/null; then
echo "✅ sqlcmd available"
else
echo "❌ sqlcmd not found"
fi

# Build the C++ extension
echo ""
echo "🔨 Building C++ extension..."
if cd mssql_python/pybind && ./build.sh && cd ../..; then
echo "✅ C++ extension built successfully"
else
echo "❌ C++ extension build failed!"
exit 1
fi

# Generate random password for SQL Server
echo ""
echo "Generating SQL Server password..."
SA_PASSWORD="$(openssl rand -base64 16 | tr -dc 'A-Za-z0-9' | head -c 16)Aa1!"
echo "$SA_PASSWORD" > /tmp/.sqlserver_sa_password
chmod 600 /tmp/.sqlserver_sa_password

# Start SQL Server container (use Azure SQL Edge for ARM64 compatibility)
# This is optional - if Docker-in-Docker fails, the devcontainer still works
echo ""
echo "Starting SQL Server container (optional)..."

ARCH=$(uname -m)
if [[ "$ARCH" == "aarch64" || "$ARCH" == "arm64" ]]; then
echo "Detected ARM64 - using Azure SQL Edge..."
docker run -e 'ACCEPT_EULA=Y' -e "MSSQL_SA_PASSWORD=$SA_PASSWORD" \
-p 1433:1433 --name sqlserver \
-d mcr.microsoft.com/azure-sql-edge:latest && SQL_STARTED=true || SQL_STARTED=false
else
echo "Detected x86_64 - using SQL Server 2025..."
docker run -e 'ACCEPT_EULA=Y' -e "MSSQL_SA_PASSWORD=$SA_PASSWORD" \
-p 1433:1433 --name sqlserver \
-d mcr.microsoft.com/mssql/server:2025-latest && SQL_STARTED=true || SQL_STARTED=false
fi

if [ "$SQL_STARTED" = "true" ]; then
echo "Waiting for SQL Server to start..."
sleep 15
else
echo "WARNING: SQL Server container failed to start (Docker issue)"
echo " You can start it manually later with:"
echo " docker run -e 'ACCEPT_EULA=Y' -e 'MSSQL_SA_PASSWORD=YourPassword123!' -p 1433:1433 --name sqlserver -d mcr.microsoft.com/azure-sql-edge:latest"
fi

# Set DB_CONNECTION_STRING environment variable (persist across all terminals)
DB_CONNECTION_STRING="Server=localhost,1433;Database=master;UID=sa;PWD=$SA_PASSWORD;TrustServerCertificate=Yes;Encrypt=Yes"

# Write to /etc/environment for system-wide persistence
echo "DB_CONNECTION_STRING=\"$DB_CONNECTION_STRING\"" | sudo tee -a /etc/environment > /dev/null

# Also add to shell rc files for immediate availability in new terminals
echo "export DB_CONNECTION_STRING=\"$DB_CONNECTION_STRING\"" >> ~/.bashrc
echo "export DB_CONNECTION_STRING=\"$DB_CONNECTION_STRING\"" >> ~/.zshrc

# Export for current session
export DB_CONNECTION_STRING

# Display completion message and next steps
echo ""
echo "=============================================="
echo "🎉 Dev environment setup complete!"
echo "=============================================="
echo ""
echo "📦 What's ready:"
echo " ✅ C++ extension built"
echo " ✅ SQL Server running (localhost:1433)"
echo " ✅ DB_CONNECTION_STRING set in environment"
echo ""
echo "🚀 Quick start - just type these commands:"
echo " python main.py → Test the connection"
echo " test → Run all pytest tests"
echo " build → Rebuild C++ extension"
echo ""
echo "=============================================="
echo ""
115 changes: 115 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Git
.git
.gitignore
.gitattributes

# Python
__pycache__
*.pyc
*.pyo
*.pyd
.Python
env
pip-log.txt
pip-delete-this-directory.txt
.tox
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.log
.mypy_cache
.pytest_cache
.hypothesis

# Distribution / packaging
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# PyInstaller
*.manifest
*.spec

# Installer logs
pip-log.txt

# Unit test / coverage reports
htmlcov/
.coverage
.coverage.*
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Documentation
docs/_build/

# PyBuilder
target/

# IDEs
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Temporary files
*.tmp
*.temp
*.log

# Node.js (if any)
node_modules/
npm-debug.log*

# CMake
CMakeCache.txt
CMakeFiles/
cmake_install.cmake
Makefile
*.cmake

# Build artifacts
*.so
*.dll
*.dylib
*.pdb
*.obj
*.exe

# Test results
test-results/
.pytest_cache/

# Azure DevOps
.azure/
Loading