Skip to content
Open
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
19 changes: 0 additions & 19 deletions .flake8

This file was deleted.

14 changes: 2 additions & 12 deletions .github/workflows/lint-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ on:
- '**.hpp'
- '.github/workflows/lint-check.yml'
- 'pyproject.toml'
- '.flake8'
- '.clang-format'
push:
branches:
Expand All @@ -39,7 +38,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install black flake8 pylint autopep8
pip install black pylint autopep8
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi

- name: Check Python formatting with Black
Expand All @@ -51,15 +50,6 @@ jobs:
}
echo "::endgroup::"

- name: Lint with Flake8
run: |
echo "::group::Flake8 Linting"
flake8 mssql_python/ tests/ --max-line-length=100 --extend-ignore=E203,W503,E501,E722,F401,F841,W293,W291,F541,F811,E402,E711,E712,E721,F821 --count --statistics || {
echo "::warning::Flake8 found linting issues (informational only, not blocking)"
}
echo "::endgroup::"
continue-on-error: true

- name: Lint with Pylint
run: |
echo "::group::Pylint Analysis"
Expand Down Expand Up @@ -159,7 +149,7 @@ jobs:
echo "❌ **Python Formatting (Black):** FAILED - Please run Black formatter" >> $GITHUB_STEP_SUMMARY
fi

echo "ℹ️ **Python Linting (Flake8, Pylint):** Informational only" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ **Python Linting (Pylint):** Informational only" >> $GITHUB_STEP_SUMMARY
echo "ℹ️ **C++ Linting (clang-format, cpplint):** Informational only" >> $GITHUB_STEP_SUMMARY

echo "" >> $GITHUB_STEP_SUMMARY
Expand Down
18 changes: 18 additions & 0 deletions build_ddbc/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
"""
build_ddbc - Build system for mssql-python native extensions.

This package provides:
1. A CLI tool: `python -m build_ddbc`
2. A PEP 517 build backend that auto-compiles ddbc_bindings

Usage:
python -m build_ddbc # Compile ddbc_bindings only
python -m build_ddbc --arch arm64 # Specify architecture (Windows)
python -m build_ddbc --coverage # Enable coverage (Linux)
python -m build # Compile + create wheel (automatic)
"""

from .compiler import compile_ddbc, get_platform_info

__all__ = ["compile_ddbc", "get_platform_info"]
__version__ = "1.2.0"
83 changes: 83 additions & 0 deletions build_ddbc/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
"""
CLI entry point for build_ddbc.

Usage:
python -m build_ddbc # Compile ddbc_bindings
python -m build_ddbc --arch arm64 # Specify architecture (Windows)
python -m build_ddbc --coverage # Enable coverage (Linux)
python -m build_ddbc --help # Show help
"""

import argparse
import sys

from . import __version__
from .compiler import compile_ddbc, get_platform_info


def main() -> int:
"""Main entry point for the CLI."""
parser = argparse.ArgumentParser(
prog="python -m build_ddbc",
description="Compile ddbc_bindings native extension for mssql-python",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
python -m build_ddbc # Build for current platform
python -m build_ddbc --arch arm64 # Build for ARM64 (Windows)
python -m build_ddbc --coverage # Build with coverage (Linux)
python -m build_ddbc --quiet # Build without output
""",
)

parser.add_argument(
"--arch", "-a",
choices=["x64", "x86", "arm64", "x86_64", "aarch64", "universal2"],
help="Target architecture (Windows: x64, x86, arm64)",
)

parser.add_argument(
"--coverage", "-c",
action="store_true",
help="Enable coverage instrumentation (Linux only)",
)

parser.add_argument(
"--quiet", "-q",
action="store_true",
help="Suppress build output",
)

parser.add_argument(
"--version", "-V",
action="version",
version=f"%(prog)s {__version__}",
)

args = parser.parse_args()

# Show platform info
if not args.quiet:
arch, platform_tag = get_platform_info()
print(f"[build_ddbc] Platform: {sys.platform}")
print(f"[build_ddbc] Architecture: {arch}")
print(f"[build_ddbc] Platform tag: {platform_tag}")
print()

try:
compile_ddbc(
arch=args.arch,
coverage=args.coverage,
verbose=not args.quiet,
)
return 0
except FileNotFoundError as e:
print(f"Error: {e}", file=sys.stderr)
return 1
except RuntimeError as e:
print(f"Build failed: {e}", file=sys.stderr)
return 1


if __name__ == "__main__":
sys.exit(main())
134 changes: 134 additions & 0 deletions build_ddbc/build_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
"""
PEP 517 Build Backend for mssql-python.

This module wraps setuptools' build backend and adds automatic
ddbc_bindings compilation before building wheels.

Usage in pyproject.toml:
[build-system]
requires = ["setuptools>=61.0", "wheel", "pybind11"]
build-backend = "build_ddbc.build_backend"
backend-path = ["."]
"""

# Import setuptools build backend - we'll wrap its functions
from setuptools.build_meta import (
build_wheel as _setuptools_build_wheel,
build_sdist as _setuptools_build_sdist,
get_requires_for_build_wheel as _get_requires_for_build_wheel,
get_requires_for_build_sdist as _get_requires_for_build_sdist,
prepare_metadata_for_build_wheel as _prepare_metadata_for_build_wheel,
)

from .compiler import compile_ddbc


# =============================================================================
# PEP 517 Required Hooks
# =============================================================================


def get_requires_for_build_wheel(config_settings=None):
"""Return build requirements for wheel."""
return _get_requires_for_build_wheel(config_settings)


def get_requires_for_build_sdist(config_settings=None):
"""Return build requirements for sdist."""
return _get_requires_for_build_sdist(config_settings)


def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
"""Prepare wheel metadata."""
return _prepare_metadata_for_build_wheel(metadata_directory, config_settings)


def build_wheel(wheel_directory, config_settings=None, metadata_directory=None):
"""
Build a wheel, compiling ddbc_bindings first.

This is the main hook - it compiles the native extension before
delegating to setuptools to create the wheel.
"""
print("[build_backend] Starting wheel build...")

# Check if we should skip compilation (e.g., for sdist-only builds)
skip_compile = False
if config_settings:
skip_compile = config_settings.get("--skip-ddbc-compile", False)

if not skip_compile:
# Extract build options from config_settings
arch = None
coverage = False

if config_settings:
arch = config_settings.get("--arch")
coverage = config_settings.get("--coverage", False)

print("[build_backend] Compiling ddbc_bindings...")
try:
compile_ddbc(arch=arch, coverage=coverage, verbose=True)
print("[build_backend] Compilation successful!")
except FileNotFoundError:
# If build scripts don't exist, assume pre-compiled binaries
print("[build_backend] Build scripts not found, assuming pre-compiled binaries")
except (RuntimeError, OSError) as e:
print(f"[build_backend] Compilation failed: {e}")
raise
else:
print("[build_backend] Skipping ddbc compilation (--skip-ddbc-compile)")

# Now build the wheel using setuptools
print("[build_backend] Creating wheel...")
return _setuptools_build_wheel(wheel_directory, config_settings, metadata_directory)


def build_sdist(sdist_directory, config_settings=None):
"""
Build a source distribution.

For sdist, we don't compile - just package the source including build scripts.
"""
print("[build_backend] Building source distribution...")
return _setuptools_build_sdist(sdist_directory, config_settings)


# =============================================================================
# Optional PEP 660 Hooks (Editable Installs)
# =============================================================================


def get_requires_for_build_editable(config_settings=None):
"""Return build requirements for editable install."""
return get_requires_for_build_wheel(config_settings)


def build_editable(wheel_directory, config_settings=None, metadata_directory=None):
"""
Build an editable wheel, compiling ddbc_bindings first.

This enables `pip install -e .` to automatically compile.
"""
print("[build_backend] Starting editable install...")

# Compile ddbc_bindings for editable installs too
print("[build_backend] Compiling ddbc_bindings for editable install...")
try:
compile_ddbc(verbose=True)
print("[build_backend] Compilation successful!")
except FileNotFoundError:
print("[build_backend] Build scripts not found, assuming pre-compiled binaries")
except (RuntimeError, OSError) as e:
print(f"[build_backend] Compilation failed: {e}")
raise

# Import here and handle absence gracefully for older setuptools versions
try:
from setuptools.build_meta import build_editable as _setuptools_build_editable
except ImportError as exc:
raise RuntimeError(
"Editable installs are not supported with this setuptools version. "
"Please install setuptools>=64.0.0 to use PEP 660 editable installs."
) from exc
return _setuptools_build_editable(wheel_directory, config_settings, metadata_directory)
Loading
Loading