Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
99839cc
async v0
LioriE Jun 7, 2026
9072ce7
Update uv.lock
LioriE Jun 7, 2026
2d54ba2
lints
LioriE Jun 7, 2026
621751b
thats ruff
LioriE Jun 7, 2026
3d9f4e8
format
LioriE Jun 8, 2026
f7b418c
other
LioriE Jun 8, 2026
14b59a8
ruff
LioriE Jun 8, 2026
43b2cc0
remove plan files and revert vscode settings
LioriE Jun 8, 2026
fadfc14
refactor(tests): centralize JWTs and shared helpers in testutils
LioriE Jun 9, 2026
95e7f8b
good
LioriE Jun 9, 2026
e050b20
refactor: remove decorative dash-banner section headers
LioriE Jun 9, 2026
b3c4428
Merge branch 'main' into feat/poc-async-base-and-totp
LioriE Jun 9, 2026
4ab5438
feat: add async support for all 8 remaining auth methods
LioriE Jun 10, 2026
6246b50
v1
LioriE Jun 10, 2026
dbc36c7
and another pass
LioriE Jun 10, 2026
553fb70
Merge branch 'feat/poc-async-base-and-totp' of github.com:descope/pyt…
LioriE Jun 10, 2026
c4d0555
fix: ruff lint errors and complete validation/compose dedup refactor
LioriE Jun 10, 2026
f1b9f12
fix: address async auth review comments
LioriE Jun 10, 2026
52c4430
fix(types): accept Optional[str] in SAML and WebAuthn base method sig…
LioriE Jun 11, 2026
9756282
fix(tests): suppress unused mock_post variables and fix bool comparison
LioriE Jun 15, 2026
88c48e5
lint-format
LioriE Jun 17, 2026
503fc92
e2e
LioriE Jun 17, 2026
0ebcc89
Merge remote-tracking branch 'origin/main' into feat/async-descope-cl…
LioriE Jun 17, 2026
8a7336e
refactor(async): make AuthAsync fully non-blocking + lazy license han…
LioriE Jun 18, 2026
2f54bf0
chore(quality): address CodeQL findings + un-skip async tests
LioriE Jun 20, 2026
2b15e66
Merge remote-tracking branch 'origin/main' into feat/async-descope-cl…
LioriE Jun 20, 2026
be21eb2
chore(merge): port actor_id support to TenantAsync, parametrize new test
LioriE Jun 20, 2026
e7e4059
test: add coverage for AuthAsync flows + common signup/login options
LioriE Jun 20, 2026
4b78f8d
Merge remote-tracking branch 'origin/feat/async-descope-client' into …
LioriE Jun 20, 2026
2a01d4d
Merge remote-tracking branch 'origin/main' into feat/async-descope-cl…
LioriE Jun 21, 2026
d7a9e3a
refactor(async): delegate OAuth/SAML/SSO exchange_token to shared Aut…
LioriE Jun 22, 2026
f90b0cf
Merge branch 'feat/async-descope-client' into feat/e2e-tests
LioriE Jun 22, 2026
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
52 changes: 50 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ on:
pull_request:
schedule:
- cron: "0 8 * * *"
workflow_dispatch:
inputs:
skip_debounce:
description: Skip the 5-minute e2e debounce (for urgent re-runs)
type: boolean
default: false

concurrency:
group: check-${{ github.ref }}
Expand Down Expand Up @@ -98,7 +104,7 @@ jobs:
- name: Install dependencies
run: uv sync --all-extras --locked
- name: Run test suite
run: uv run coverage run -m pytest tests
run: uv run coverage run -m pytest tests --ignore=tests/e2e
env:
COVERAGE_FILE: "coverage.${{ matrix.os }}.${{ matrix.py }}"
- name: Store coverage file
Expand Down Expand Up @@ -143,6 +149,48 @@ jobs:
name: python-coverage-comment-action
path: python-coverage-comment-action.txt

e2e-sandbox:
name: E2E Tests
runs-on: ubuntu-latest
permissions:
checks: write
pull-requests: write
if: >
github.event_name != 'pull_request' ||
github.event.pull_request.draft != true
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Install uv
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
with:
enable-cache: true
python-version: "3.13"
- name: Install dependencies
run: uv sync --all-extras --locked
- name: Debounce
# Waits 1 min before running so rapid pushes to the same PR cancel the stale run
# (via the global cancel-in-progress) before any e2e work starts.
# Skip via the 'quick-e2e' PR label or the skip_debounce workflow_dispatch input.
if: >
github.event_name == 'pull_request' &&
github.actor != 'renovate[bot]' &&
!contains(github.event.pull_request.labels.*.name, 'quick-e2e') &&
inputs.skip_debounce != 'true'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 LOW: This skip_debounce check is dead. The step's first condition requires github.event_name == 'pull_request', but the skip_debounce input only exists for workflow_dispatch events. On a PR run inputs.skip_debounce is always empty, so != 'true' is always true; on a dispatch run the step is skipped entirely. The input (and the comment promising it skips the debounce) never has any effect.

run: sleep 60
- name: Run e2e tests
if: github.actor != 'renovate[bot]'
run: uv run pytest tests/e2e -v -m e2e --junitxml=e2e-report.xml
env:
DESCOPE_PROJECT_ID: ${{ secrets.DESCOPE_SANDBOX_PROJECT_ID }}
DESCOPE_MANAGEMENT_KEY: ${{ secrets.DESCOPE_SANDBOX_MANAGEMENT_KEY }}
DESCOPE_BASE_URI: ${{ secrets.DESCOPE_SANDBOX_BASE_URI }}
- name: Publish e2e test report
if: always() && github.actor != 'renovate[bot]'
uses: mikepenz/action-junit-report@3a81627bfac62268172037048872e8ebd4207e6d # v6.4.1
with:
report_paths: e2e-report.xml
check_name: E2E Test Report

gitleaks:
name: gitleaks
runs-on: ubuntu-latest
Expand All @@ -159,7 +207,7 @@ jobs:
name: All Checks Passed
runs-on: ubuntu-latest
permissions: {}
needs: [validate-pr-title, lint, build, coverage, gitleaks]
needs: [validate-pr-title, lint, build, coverage, gitleaks, e2e-sandbox]
if: always() && !cancelled() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled')
steps:
- name: Yey, all checks passed!
Expand Down
16 changes: 16 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
title = "python-sdk gitleaks config"

[allowlist]
description = "False positives: test fixture JWTs, coverage artifacts, README examples"
regexes = [
# Fake JWTs used as test fixtures (kid: 2Bt5WLccLUey1Dp7utptZb3Fx9K)
'''eyJhbGciOiJFUzM4NCIsImtpZCI6IjJCdDVXTGNjTFVleTFEcDd1dHB0WmIzRng5SyIsInR5cCI6IkpX''',
# Fake JWTs used as test fixtures (kid: P2CtzUhdqpIF2ys9gg7ms06UvtC4)
'''eyJhbGciOiJFUzM4NCIsImtpZCI6IlAyQ3R6VWhkcXBJRjJ5czlnZzdtczA2VXZ0QzQiLCJ0eXAiOiJK''',
# Example password in README docs
'''qYlvi65KaX''',
]
paths = [
# Coverage report artifacts
'''htmlcov/''',
]
2 changes: 2 additions & 0 deletions .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ e7f5ad4253ad82236a5cff5f8c06878bfb190b00:tests/test_descope_client.py:jwt:185
e7f5ad4253ad82236a5cff5f8c06878bfb190b00:tests/test_descope_client.py:jwt:197
ece761372c78a9ad8a57da5f6d13431d298a99db:tests/test_auth.py:jwt:562
f3ec873c83a7067a1226d8b712b756b1b599fb3b:tests/test_descope_client.py:jwt:519
e44fd5977ffd62c56f63c32e2422bf2c0e87c816:tests/test_descope_client_parity.py:jwt:100
e44fd5977ffd62c56f63c32e2422bf2c0e87c816:tests/test_descope_client_parity.py:jwt:761
b6a2e217be5dceb6c85332d2e193619894d3a36e:README.md:generic-api-key:1349
b6a2e217be5dceb6c85332d2e193619894d3a36e:README.md:generic-api-key:1372
c751b1e9df5dcb6e6b3a62601174065ebf03144f:README.md:generic-api-key:1358
Expand Down
29 changes: 29 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -575,12 +575,14 @@ except AuthException as e:
```

**Important Notes:**

- Verbose mode is **disabled by default** (no performance impact when not needed)
- When enabled, only the **most recent** HTTP response is stored
- `get_last_response()` returns `None` when verbose mode is disabled
- The response object provides dict-like access to JSON data while also exposing HTTP metadata

**Available metadata on response objects:**

- `response.headers` - HTTP response headers (dict-like object)
- `response.status_code` - HTTP status code (int)
- `response.text` - Raw response body as text (str)
Expand Down Expand Up @@ -1922,6 +1924,33 @@ Running all tests with coverage:
uv run pytest --junitxml=/tmp/pytest.xml --cov-report=term-missing:skip-covered --cov=descope tests/ --cov-report=xml:/tmp/cov.xml
```

### Running e2e tests

The `tests/e2e/` suite exercises the SDK against a real Descope backend. Set the
following environment variables before running:

| Variable | Required | Description |
| ------------------------ | -------- | --------------------------------- |
| `DESCOPE_PROJECT_ID` | ✅ | The project to run tests against |
| `DESCOPE_MANAGEMENT_KEY` | ✅ | A management key for that project |
| `DESCOPE_BASE_URI` | Optional | Override the API base URL |

**Project prerequisites:** the e2e project must be configured with:

- **Password authentication enabled** with policy: minLength ≥ 9, uppercase required, non-alphanumeric character required (needed by `test_password.py`).
- **Magic-link / email authentication enabled** (needed by `test_magiclink.py`).
- **Default flows present** (needed by `test_flow.py`).

```bash
uv run pytest tests/e2e -v
```

To run the full test suite while skipping e2e tests (default CI behaviour):

```bash
uv run pytest tests -m "not e2e"
```

### Lint and format

```bash
Expand Down
2 changes: 2 additions & 0 deletions descope/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
SignUpOptions,
)
from descope.descope_client import DescopeClient
from descope.descope_client_async import DescopeClientAsync
from descope.exceptions import (
API_RATE_LIMIT_RETRY_AFTER_HEADER,
ERROR_TYPE_API_RATE_LIMIT,
Expand Down Expand Up @@ -64,6 +65,7 @@
"DeliveryMethod",
"LoginOptions",
"SignUpOptions",
"DescopeClientAsync",
"DescopeClient",
"API_RATE_LIMIT_RETRY_AFTER_HEADER",
"ERROR_TYPE_API_RATE_LIMIT",
Expand Down
Loading
Loading