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
32 changes: 30 additions & 2 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,44 @@ uv sync --locked --dev # Install package in development mode with dev dependenci
### Code Quality

```bash
ur run ruff format . # Format code
uv run ruff format . # Format code
uv run ruff format --check . # Check formatting without making changes
uv run ruff check . # Lint code
uv run mypy # Type checking
```

### Testing

The SDK uses [nox](https://nox.thea.codes/) with [nox-uv](https://github.com/dantebben/nox-uv) for multi-version Python testing. This ensures compatibility across all supported Python versions (3.8-3.14).

**Quick testing with the test script:**

```bash
./scripts/test.sh # Run tests on all Python versions
./scripts/test.sh 3.12 # Run tests on Python 3.12 only
./scripts/test.sh 3.11 3.12 # Run tests on Python 3.11 and 3.12
./scripts/test.sh --coverage # Run tests with coverage on all versions
./scripts/test.sh --ci # Run full CI checks (lint, type, tests)
./scripts/test.sh --fresh # Recreate virtual environments
./scripts/test.sh 3.12 -- -k "test_sso" -v # Pass pytest arguments
```

**Direct nox commands:**

```bash
uv run nox # Run tests on all Python versions
uv run nox -s tests-3.12 # Run tests on specific Python version
uv run nox -s coverage # Run tests with coverage
uv run nox -s lint # Run linting
uv run nox -s typecheck # Run type checking
uv run nox -s ci # Run all CI checks
uv run nox -l # List all available sessions
```

**Single-version testing (faster for development):**

```bash
uv run pytest # Run all tests
uv run pytest # Run all tests on current Python
uv run pytest tests/test_sso.py # Run specific test file
uv run pytest -k "test_name" # Run tests matching pattern
uv run pytest --cov=workos # Run tests with coverage
Expand Down
72 changes: 72 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
"""Nox configuration for multi-version Python testing.

This configuration uses nox-uv for fast, reproducible environment management
with uv's lockfile. Run `nox` to test against all supported Python versions,
or use `nox -s tests-3.12` to test a specific version.
"""

from __future__ import annotations

import nox
from nox_uv import session

# Use uv as the default venv backend for speed
nox.options.default_venv_backend = "uv"

# Reuse virtual environments by default for faster local iteration
nox.options.reuse_venv = "yes"

# All Python versions supported by the SDK (must match CI matrix)
PYTHON_VERSIONS = ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]

# Default sessions to run
nox.options.sessions = ["tests"]


@session(python=PYTHON_VERSIONS, uv_groups=["test"])
def tests(s: nox.Session) -> None:
"""Run the test suite against all supported Python versions."""
args = s.posargs or []
s.run("pytest", *args)


@session(python=PYTHON_VERSIONS, uv_groups=["test"])
def coverage(s: nox.Session) -> None:
"""Run tests with coverage reporting."""
s.run("pytest", "--cov=workos", "--cov-report=term-missing", *s.posargs)


@session(uv_only_groups=["lint"])
def lint(s: nox.Session) -> None:
"""Run linting with ruff."""
s.run("ruff", "check", ".")


@session(uv_only_groups=["lint"])
def format(s: nox.Session) -> None:
"""Check code formatting with ruff."""
s.run("ruff", "format", "--check", ".")


@session(uv_only_groups=["lint"])
def format_fix(s: nox.Session) -> None:
"""Apply code formatting with ruff."""
s.run("ruff", "format", ".")


@session(uv_groups=["type_check"])
def typecheck(s: nox.Session) -> None:
"""Run type checking with mypy."""
s.run("mypy")


@session(uv_groups=["test", "lint", "type_check"])
def ci(s: nox.Session) -> None:
"""Run all CI checks (format, lint, typecheck, tests) for a single Python version.

This is useful for quick local validation before pushing.
"""
s.run("ruff", "format", "--check", ".")
s.run("ruff", "check", ".")
s.run("mypy")
s.run("pytest")
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ dev = [
{ include-group = "test" },
{ include-group = "lint" },
{ include-group = "type_check" },
{ include-group = "nox" },
]
test = [
"pytest==8.3.4",
Expand All @@ -34,6 +35,10 @@ test = [
]
lint = ["ruff==0.14.5"]
type_check = ["mypy==1.14.1"]
nox = [
"nox>=2024.10.9 ; python_version >= '3.9'",
"nox-uv>=0.7.0 ; python_version >= '3.9'",
]


[tool.mypy]
Expand Down
83 changes: 83 additions & 0 deletions scripts/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#!/usr/bin/env bash
#
# Usage:
# ./scripts/test.sh # Run tests on all Python versions
# ./scripts/test.sh 3.12 # Run tests on Python 3.12 only
# ./scripts/test.sh 3.11 3.12 # Run tests on Python 3.11 and 3.12
# ./scripts/test.sh --coverage # Run tests with coverage on all versions
# ./scripts/test.sh --ci # Run full CI checks (lint, type, tests)
# ./scripts/test.sh --fresh # Recreate virtual environments
#
# Additional pytest arguments can be passed after --, e.g.:
# ./scripts/test.sh 3.12 -- -k "test_sso" -v

set -e

# Check if uv is available
if ! command -v uv &>/dev/null; then
echo "Error: uv is not installed or not in PATH"
echo "Install uv: https://docs.astral.sh/uv/getting-started/installation/"
exit 1
fi

# Parse arguments
PYTHON_VERSIONS=()
NOX_ARGS=()
PYTEST_ARGS=()
SESSION="tests"
FRESH=false
PARSING_PYTEST_ARGS=false

for arg in "$@"; do
if [[ "$PARSING_PYTEST_ARGS" == true ]]; then
PYTEST_ARGS+=("$arg")
elif [[ "$arg" == "--" ]]; then
PARSING_PYTEST_ARGS=true
elif [[ "$arg" == "--coverage" ]]; then
SESSION="coverage"
elif [[ "$arg" == "--ci" ]]; then
SESSION="ci"
elif [[ "$arg" == "--fresh" ]]; then
FRESH=true
elif [[ "$arg" =~ ^3\.[0-9]+$ ]]; then
PYTHON_VERSIONS+=("$arg")
else
NOX_ARGS+=("$arg")
fi
done

# Build the nox command
CMD=(uv run nox -s)

if [[ ${#PYTHON_VERSIONS[@]} -gt 0 ]]; then
# Run specific Python versions
SESSIONS=""
for ver in "${PYTHON_VERSIONS[@]}"; do
if [[ -n "$SESSIONS" ]]; then
SESSIONS="$SESSIONS,"
fi
SESSIONS="${SESSIONS}${SESSION}-${ver}"
done
CMD+=("$SESSIONS")
else
# Run all versions
CMD+=("$SESSION")
fi

# Add fresh flag if requested
if [[ "$FRESH" == true ]]; then
CMD+=(--reuse-venv=never)
fi

# Add any additional nox args
if [[ ${#NOX_ARGS[@]} -gt 0 ]]; then
CMD+=("${NOX_ARGS[@]}")
fi

# Add pytest args if provided
if [[ ${#PYTEST_ARGS[@]} -gt 0 ]]; then
CMD+=(-- "${PYTEST_ARGS[@]}")
fi

echo "Running: ${CMD[*]}"
exec "${CMD[@]}"
Loading