didit-sdk 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,49 @@
1
+ # Python & bytecode
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+
8
+ # Virtual environments
9
+ .venv/
10
+ venv/
11
+ ENV/
12
+ env/
13
+
14
+ # Distribution & packaging
15
+ build/
16
+ develop-eggs/
17
+ dist/
18
+ downloads/
19
+ eggs/
20
+ .eggs/
21
+ lib/
22
+ lib64/
23
+ parts/
24
+ sdist/
25
+ var/
26
+ wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+
31
+ # Testing & quality
32
+ .pytest_cache/
33
+ .coverage
34
+ htmlcov/
35
+ coverage.xml
36
+ .mypy_cache/
37
+ .ruff_cache/
38
+ .hypothesis/
39
+
40
+ # Private workspace & audit roadmap
41
+ .roadmap.md
42
+ .audit/
43
+
44
+ # IDE & OS
45
+ .vscode/
46
+ .idea/
47
+ .DS_Store
48
+ *.swp
49
+ *.swo
@@ -0,0 +1,28 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Agustin Saiz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
22
+
23
+ ---
24
+
25
+ Disclaimer:
26
+ This project is an independent community library and is not affiliated,
27
+ endorsed, or sponsored by Didit Protocol Inc. or its subsidiaries.
28
+ "Didit" is a trademark of its respective owner.
@@ -0,0 +1,262 @@
1
+ Metadata-Version: 2.5
2
+ Name: didit-sdk
3
+ Version: 0.1.0
4
+ Summary: Unofficial Python SDK for Didit (didit.me) Identity Verification & KYC
5
+ Project-URL: Homepage, https://github.com/agustin18/didit-sdk
6
+ Project-URL: Documentation, https://github.com/agustin18/didit-sdk#readme
7
+ Project-URL: Repository, https://github.com/agustin18/didit-sdk
8
+ Project-URL: Issues, https://github.com/agustin18/didit-sdk/issues
9
+ Author-email: Agustin Saiz <agustinsaiz02@gmail.com>
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: biometrics,didit,fastapi,identity-verification,kyc,sdk,webhooks
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Security :: Cryptography
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: httpx>=0.25.0
26
+ Requires-Dist: pydantic>=2.0.0
27
+ Provides-Extra: all
28
+ Requires-Dist: fastapi>=0.100.0; extra == 'all'
29
+ Provides-Extra: dev
30
+ Requires-Dist: fastapi>=0.100.0; extra == 'dev'
31
+ Requires-Dist: httpx>=0.25.0; extra == 'dev'
32
+ Requires-Dist: mypy>=1.10.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=5.0.0; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
36
+ Requires-Dist: respx>=0.21.0; extra == 'dev'
37
+ Requires-Dist: ruff>=0.4.0; extra == 'dev'
38
+ Provides-Extra: fastapi
39
+ Requires-Dist: fastapi>=0.100.0; extra == 'fastapi'
40
+ Description-Content-Type: text/markdown
41
+
42
+ # didit-sdk
43
+
44
+ [![CI](https://github.com/agustin18/didit-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/agustin18/didit-sdk/actions/workflows/ci.yml)
45
+ [![PyPI version](https://img.shields.io/pypi/v/didit-sdk.svg)](https://pypi.org/project/didit-sdk/)
46
+ [![Python versions](https://img.shields.io/pypi/pyversions/didit-sdk.svg)](https://pypi.org/project/didit-sdk/)
47
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
48
+ [![Checked with mypy](https://img.shields.io/badge/mypy-strict-blue)](https://mypy-lang.org/)
49
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
50
+
51
+ Official-grade, community-maintained Python SDK for [Didit](https://didit.me) Identity Verification & KYC.
52
+
53
+ > [!IMPORTANT]
54
+ > **Legal Disclaimer**: This is an independent, community-driven open-source project and is **not** officially affiliated with, endorsed by, or sponsored by Didit Protocol Inc. All trademarks, service marks, and company names are the property of their respective owners.
55
+
56
+ ---
57
+
58
+ ## Highlights
59
+
60
+ - **Ergonomic Sync & Async**: Dual-client architecture built on top of high-performance `httpx`.
61
+ - **Strictly Typed & Validated**: 100% type annotations (PEP 561 compliant with `py.typed`) and robust Pydantic v2 domain models.
62
+ - **Cryptographic Security**: Constant-time HMAC-SHA256 signature verification supporting canonical JSON float-normalization (`X-Signature-V2`) and replay-attack protection via timestamp freshness windows.
63
+ - **FastAPI Integration**: Plug-and-play `DiditWebhookGuard` dependency for securing webhook endpoints with zero boilerplate.
64
+ - **Zero-Network Simulation Mode**: Built-in `SimulatedDidit` and `SimulatedAsyncDidit` to run unit tests and local end-to-end user flows completely offline without live credentials.
65
+ - **Resilient Error Hierarchy**: Typed exceptions (`DiditAuthenticationError`, `DiditRateLimitError`, `DiditNotFoundError`, `DiditServerError`) with automated rate-limit retry duration parsing.
66
+
67
+ ---
68
+
69
+ ## Installation
70
+
71
+ ```bash
72
+ # Core SDK (httpx + pydantic)
73
+ pip install didit-sdk
74
+
75
+ # With FastAPI integration
76
+ pip install "didit-sdk[fastapi]"
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Quickstart
82
+
83
+ ### 1. Synchronous Client
84
+
85
+ ```python
86
+ from didit import Didit, SessionStatus
87
+
88
+ # Initialize client (falls back to DIDIT_API_KEY environment variable if omitted)
89
+ client = Didit(api_key="your_api_key", webhook_secret="your_webhook_secret")
90
+
91
+ # Create a verification session
92
+ session = client.sessions.create(
93
+ vendor_data="user_12345",
94
+ workflow_id="wf_kyc_standard",
95
+ callback="https://yourapp.com/kyc/complete",
96
+ language="es",
97
+ )
98
+
99
+ print(f"Verification URL: {session.url}")
100
+ print(f"Session ID: {session.session_id}")
101
+
102
+ # Fetch verification decision immediately:
103
+ decision = client.sessions.get_decision(session.session_id)
104
+
105
+ # Or poll until a terminal outcome (Approved or Declined) is reached:
106
+ decision = client.sessions.poll_decision(session.session_id, timeout=60.0, interval=2.0)
107
+ if decision.status == SessionStatus.APPROVED:
108
+ print(f"User approved! Document: {decision.document.document_number}")
109
+ ```
110
+
111
+ ### 2. Asynchronous Client (`asyncio`)
112
+
113
+ ```python
114
+ import asyncio
115
+ from didit import AsyncDidit, SessionStatus
116
+
117
+
118
+ async def main():
119
+ async with AsyncDidit(api_key="your_api_key") as client:
120
+ session = await client.sessions.create(
121
+ vendor_data="user_987",
122
+ workflow_id="wf_kyc_standard",
123
+ )
124
+ print(f"Session URL: {session.url}")
125
+
126
+ decision = await client.sessions.get_decision(session.session_id)
127
+ if decision.status.is_terminal:
128
+ print(f"Final outcome: {decision.status}")
129
+
130
+
131
+ asyncio.run(main())
132
+ ```
133
+
134
+ ---
135
+
136
+ ## Securing Webhooks with FastAPI
137
+
138
+ Didit dispatches signed HTTP POST events upon verification completion. `didit-sdk` provides a dedicated FastAPI dependency to verify signatures in constant time and prevent replay attacks:
139
+
140
+ ```python
141
+ from fastapi import FastAPI, Depends
142
+ from didit import WebhookPayload, SessionStatus
143
+ from didit.integrations.fastapi import DiditWebhookGuard
144
+
145
+ app = FastAPI()
146
+
147
+ # Guard reads secret from argument or DIDIT_WEBHOOK_SECRET env var
148
+ webhook_guard = DiditWebhookGuard(secret="whsec_...")
149
+
150
+
151
+ @app.post("/api/v1/webhooks/didit")
152
+ async def handle_didit_event(
153
+ payload: WebhookPayload = Depends(webhook_guard),
154
+ ):
155
+ print(f"Received event for session: {payload.session_id}")
156
+
157
+ if payload.status == SessionStatus.APPROVED:
158
+ # Mark user verified in your database
159
+ ...
160
+ elif payload.status == SessionStatus.DECLINED:
161
+ # Handle rejection
162
+ ...
163
+
164
+ return {"received": True}
165
+ ```
166
+
167
+ ---
168
+
169
+ ## Testing & Offline Simulation
170
+
171
+ Developing without live credentials or mock servers? Use the built-in simulator:
172
+
173
+ ```python
174
+ from didit import SimulatedDidit, SessionStatus
175
+
176
+ # Create in-memory client
177
+ sim = SimulatedDidit(webhook_secret="test_secret")
178
+
179
+ # 1. Create a simulated session
180
+ session = sim.sessions.create(vendor_data="dev_user", workflow_id="wf_dev")
181
+ assert session.session_id.startswith("sim_")
182
+
183
+ # 2. Simulate user passing identity check
184
+ sim.approve_session(session.session_id)
185
+
186
+ decision = sim.sessions.get_decision(session.session_id)
187
+ assert decision.status == SessionStatus.APPROVED
188
+
189
+ # 3. Generate signed webhook payloads to test your local receiver
190
+ raw_body, headers = sim.generate_webhook_event(session.session_id)
191
+ # headers contain valid X-Signature-V2 and fresh X-Timestamp!
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Exception Handling
197
+
198
+ All client errors inherit from `DiditError`:
199
+
200
+ ```python
201
+ from didit import Didit
202
+ from didit.errors import (
203
+ DiditAuthenticationError,
204
+ DiditNotFoundError,
205
+ DiditRateLimitError,
206
+ DiditServerError,
207
+ )
208
+
209
+ client = Didit()
210
+
211
+ try:
212
+ decision = client.sessions.get_decision("non_existent_session")
213
+ except DiditNotFoundError:
214
+ print("Session not found")
215
+ except DiditRateLimitError as exc:
216
+ print(f"Rate limited. Retry after {exc.retry_after} seconds.")
217
+ except DiditAuthenticationError:
218
+ print("Invalid API key")
219
+ except DiditServerError as exc:
220
+ print(f"Didit server error ({exc.status_code}): {exc.response_body}")
221
+ ```
222
+
223
+ ---
224
+
225
+ ## Environment Variables
226
+
227
+ | Variable | Default | Description |
228
+ |---|---|---|
229
+ | `DIDIT_API_KEY` | *None* (Required) | Your Didit secret API key |
230
+ | `DIDIT_BASE_URL` | `https://verification.didit.me/v3` | Didit API base URL |
231
+ | `DIDIT_WEBHOOK_SECRET` | *None* | Shared webhook HMAC secret |
232
+ | `DIDIT_TIMEOUT` | `30.0` | HTTP request timeout in seconds |
233
+ | `DIDIT_MAX_RETRIES` | `2` | Maximum retry attempts for transient errors |
234
+
235
+ ---
236
+
237
+ ## Development & Testing
238
+
239
+ ```bash
240
+ # Clone the repository
241
+ git clone https://github.com/agustin18/didit-sdk.git
242
+ cd didit-sdk
243
+
244
+ # Install dependencies with uv
245
+ uv sync --extra dev
246
+
247
+ # Run unit tests with 100% coverage gate
248
+ uv run pytest --cov=didit --cov-report=term-missing
249
+
250
+ # Lint & Format check
251
+ uv run ruff check .
252
+ uv run ruff format --check .
253
+
254
+ # Strict type check
255
+ uv run mypy src/didit
256
+ ```
257
+
258
+ ---
259
+
260
+ ## License
261
+
262
+ This project is licensed under the terms of the [MIT License](LICENSE).
@@ -0,0 +1,221 @@
1
+ # didit-sdk
2
+
3
+ [![CI](https://github.com/agustin18/didit-sdk/actions/workflows/ci.yml/badge.svg)](https://github.com/agustin18/didit-sdk/actions/workflows/ci.yml)
4
+ [![PyPI version](https://img.shields.io/pypi/v/didit-sdk.svg)](https://pypi.org/project/didit-sdk/)
5
+ [![Python versions](https://img.shields.io/pypi/pyversions/didit-sdk.svg)](https://pypi.org/project/didit-sdk/)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
+ [![Checked with mypy](https://img.shields.io/badge/mypy-strict-blue)](https://mypy-lang.org/)
8
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
9
+
10
+ Official-grade, community-maintained Python SDK for [Didit](https://didit.me) Identity Verification & KYC.
11
+
12
+ > [!IMPORTANT]
13
+ > **Legal Disclaimer**: This is an independent, community-driven open-source project and is **not** officially affiliated with, endorsed by, or sponsored by Didit Protocol Inc. All trademarks, service marks, and company names are the property of their respective owners.
14
+
15
+ ---
16
+
17
+ ## Highlights
18
+
19
+ - **Ergonomic Sync & Async**: Dual-client architecture built on top of high-performance `httpx`.
20
+ - **Strictly Typed & Validated**: 100% type annotations (PEP 561 compliant with `py.typed`) and robust Pydantic v2 domain models.
21
+ - **Cryptographic Security**: Constant-time HMAC-SHA256 signature verification supporting canonical JSON float-normalization (`X-Signature-V2`) and replay-attack protection via timestamp freshness windows.
22
+ - **FastAPI Integration**: Plug-and-play `DiditWebhookGuard` dependency for securing webhook endpoints with zero boilerplate.
23
+ - **Zero-Network Simulation Mode**: Built-in `SimulatedDidit` and `SimulatedAsyncDidit` to run unit tests and local end-to-end user flows completely offline without live credentials.
24
+ - **Resilient Error Hierarchy**: Typed exceptions (`DiditAuthenticationError`, `DiditRateLimitError`, `DiditNotFoundError`, `DiditServerError`) with automated rate-limit retry duration parsing.
25
+
26
+ ---
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ # Core SDK (httpx + pydantic)
32
+ pip install didit-sdk
33
+
34
+ # With FastAPI integration
35
+ pip install "didit-sdk[fastapi]"
36
+ ```
37
+
38
+ ---
39
+
40
+ ## Quickstart
41
+
42
+ ### 1. Synchronous Client
43
+
44
+ ```python
45
+ from didit import Didit, SessionStatus
46
+
47
+ # Initialize client (falls back to DIDIT_API_KEY environment variable if omitted)
48
+ client = Didit(api_key="your_api_key", webhook_secret="your_webhook_secret")
49
+
50
+ # Create a verification session
51
+ session = client.sessions.create(
52
+ vendor_data="user_12345",
53
+ workflow_id="wf_kyc_standard",
54
+ callback="https://yourapp.com/kyc/complete",
55
+ language="es",
56
+ )
57
+
58
+ print(f"Verification URL: {session.url}")
59
+ print(f"Session ID: {session.session_id}")
60
+
61
+ # Fetch verification decision immediately:
62
+ decision = client.sessions.get_decision(session.session_id)
63
+
64
+ # Or poll until a terminal outcome (Approved or Declined) is reached:
65
+ decision = client.sessions.poll_decision(session.session_id, timeout=60.0, interval=2.0)
66
+ if decision.status == SessionStatus.APPROVED:
67
+ print(f"User approved! Document: {decision.document.document_number}")
68
+ ```
69
+
70
+ ### 2. Asynchronous Client (`asyncio`)
71
+
72
+ ```python
73
+ import asyncio
74
+ from didit import AsyncDidit, SessionStatus
75
+
76
+
77
+ async def main():
78
+ async with AsyncDidit(api_key="your_api_key") as client:
79
+ session = await client.sessions.create(
80
+ vendor_data="user_987",
81
+ workflow_id="wf_kyc_standard",
82
+ )
83
+ print(f"Session URL: {session.url}")
84
+
85
+ decision = await client.sessions.get_decision(session.session_id)
86
+ if decision.status.is_terminal:
87
+ print(f"Final outcome: {decision.status}")
88
+
89
+
90
+ asyncio.run(main())
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Securing Webhooks with FastAPI
96
+
97
+ Didit dispatches signed HTTP POST events upon verification completion. `didit-sdk` provides a dedicated FastAPI dependency to verify signatures in constant time and prevent replay attacks:
98
+
99
+ ```python
100
+ from fastapi import FastAPI, Depends
101
+ from didit import WebhookPayload, SessionStatus
102
+ from didit.integrations.fastapi import DiditWebhookGuard
103
+
104
+ app = FastAPI()
105
+
106
+ # Guard reads secret from argument or DIDIT_WEBHOOK_SECRET env var
107
+ webhook_guard = DiditWebhookGuard(secret="whsec_...")
108
+
109
+
110
+ @app.post("/api/v1/webhooks/didit")
111
+ async def handle_didit_event(
112
+ payload: WebhookPayload = Depends(webhook_guard),
113
+ ):
114
+ print(f"Received event for session: {payload.session_id}")
115
+
116
+ if payload.status == SessionStatus.APPROVED:
117
+ # Mark user verified in your database
118
+ ...
119
+ elif payload.status == SessionStatus.DECLINED:
120
+ # Handle rejection
121
+ ...
122
+
123
+ return {"received": True}
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Testing & Offline Simulation
129
+
130
+ Developing without live credentials or mock servers? Use the built-in simulator:
131
+
132
+ ```python
133
+ from didit import SimulatedDidit, SessionStatus
134
+
135
+ # Create in-memory client
136
+ sim = SimulatedDidit(webhook_secret="test_secret")
137
+
138
+ # 1. Create a simulated session
139
+ session = sim.sessions.create(vendor_data="dev_user", workflow_id="wf_dev")
140
+ assert session.session_id.startswith("sim_")
141
+
142
+ # 2. Simulate user passing identity check
143
+ sim.approve_session(session.session_id)
144
+
145
+ decision = sim.sessions.get_decision(session.session_id)
146
+ assert decision.status == SessionStatus.APPROVED
147
+
148
+ # 3. Generate signed webhook payloads to test your local receiver
149
+ raw_body, headers = sim.generate_webhook_event(session.session_id)
150
+ # headers contain valid X-Signature-V2 and fresh X-Timestamp!
151
+ ```
152
+
153
+ ---
154
+
155
+ ## Exception Handling
156
+
157
+ All client errors inherit from `DiditError`:
158
+
159
+ ```python
160
+ from didit import Didit
161
+ from didit.errors import (
162
+ DiditAuthenticationError,
163
+ DiditNotFoundError,
164
+ DiditRateLimitError,
165
+ DiditServerError,
166
+ )
167
+
168
+ client = Didit()
169
+
170
+ try:
171
+ decision = client.sessions.get_decision("non_existent_session")
172
+ except DiditNotFoundError:
173
+ print("Session not found")
174
+ except DiditRateLimitError as exc:
175
+ print(f"Rate limited. Retry after {exc.retry_after} seconds.")
176
+ except DiditAuthenticationError:
177
+ print("Invalid API key")
178
+ except DiditServerError as exc:
179
+ print(f"Didit server error ({exc.status_code}): {exc.response_body}")
180
+ ```
181
+
182
+ ---
183
+
184
+ ## Environment Variables
185
+
186
+ | Variable | Default | Description |
187
+ |---|---|---|
188
+ | `DIDIT_API_KEY` | *None* (Required) | Your Didit secret API key |
189
+ | `DIDIT_BASE_URL` | `https://verification.didit.me/v3` | Didit API base URL |
190
+ | `DIDIT_WEBHOOK_SECRET` | *None* | Shared webhook HMAC secret |
191
+ | `DIDIT_TIMEOUT` | `30.0` | HTTP request timeout in seconds |
192
+ | `DIDIT_MAX_RETRIES` | `2` | Maximum retry attempts for transient errors |
193
+
194
+ ---
195
+
196
+ ## Development & Testing
197
+
198
+ ```bash
199
+ # Clone the repository
200
+ git clone https://github.com/agustin18/didit-sdk.git
201
+ cd didit-sdk
202
+
203
+ # Install dependencies with uv
204
+ uv sync --extra dev
205
+
206
+ # Run unit tests with 100% coverage gate
207
+ uv run pytest --cov=didit --cov-report=term-missing
208
+
209
+ # Lint & Format check
210
+ uv run ruff check .
211
+ uv run ruff format --check .
212
+
213
+ # Strict type check
214
+ uv run mypy src/didit
215
+ ```
216
+
217
+ ---
218
+
219
+ ## License
220
+
221
+ This project is licensed under the terms of the [MIT License](LICENSE).
@@ -0,0 +1,134 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "didit-sdk"
7
+ version = "0.1.0"
8
+ description = "Unofficial Python SDK for Didit (didit.me) Identity Verification & KYC"
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [
13
+ { name = "Agustin Saiz", email = "agustinsaiz02@gmail.com" }
14
+ ]
15
+ keywords = [
16
+ "didit",
17
+ "kyc",
18
+ "identity-verification",
19
+ "biometrics",
20
+ "fastapi",
21
+ "sdk",
22
+ "webhooks"
23
+ ]
24
+ classifiers = [
25
+ "Development Status :: 4 - Beta",
26
+ "Intended Audience :: Developers",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Programming Language :: Python :: 3",
29
+ "Programming Language :: Python :: 3.10",
30
+ "Programming Language :: Python :: 3.11",
31
+ "Programming Language :: Python :: 3.12",
32
+ "Programming Language :: Python :: 3.13",
33
+ "Topic :: Software Development :: Libraries :: Python Modules",
34
+ "Topic :: Security :: Cryptography",
35
+ "Typing :: Typed",
36
+ ]
37
+ dependencies = [
38
+ "httpx>=0.25.0",
39
+ "pydantic>=2.0.0",
40
+ ]
41
+
42
+ [project.optional-dependencies]
43
+ fastapi = [
44
+ "fastapi>=0.100.0",
45
+ ]
46
+ all = [
47
+ "fastapi>=0.100.0",
48
+ ]
49
+ dev = [
50
+ "pytest>=8.0.0",
51
+ "pytest-asyncio>=0.23.0",
52
+ "pytest-cov>=5.0.0",
53
+ "respx>=0.21.0",
54
+ "ruff>=0.4.0",
55
+ "mypy>=1.10.0",
56
+ "fastapi>=0.100.0",
57
+ "httpx>=0.25.0",
58
+ ]
59
+
60
+ [project.urls]
61
+ Homepage = "https://github.com/agustin18/didit-sdk"
62
+ Documentation = "https://github.com/agustin18/didit-sdk#readme"
63
+ Repository = "https://github.com/agustin18/didit-sdk"
64
+ Issues = "https://github.com/agustin18/didit-sdk/issues"
65
+
66
+ [tool.hatch.build.targets.wheel]
67
+ packages = ["src/didit"]
68
+
69
+ [tool.hatch.build.targets.sdist]
70
+ include = [
71
+ "/src",
72
+ "/tests",
73
+ "/README.md",
74
+ "/LICENSE",
75
+ "/pyproject.toml",
76
+ ]
77
+ exclude = [
78
+ ".roadmap.md",
79
+ ".audit",
80
+ ]
81
+
82
+ [tool.pytest.ini_options]
83
+ minversion = "8.0"
84
+ addopts = "-ra -q --strict-markers"
85
+ testpaths = ["tests"]
86
+ asyncio_mode = "auto"
87
+ asyncio_default_fixture_loop_scope = "function"
88
+
89
+ [tool.coverage.run]
90
+ source = ["src/didit"]
91
+ branch = true
92
+
93
+ [tool.coverage.report]
94
+ show_missing = true
95
+ fail_under = 100
96
+ exclude_lines = [
97
+ "pragma: no cover",
98
+ "def __repr__",
99
+ "raise NotImplementedError",
100
+ "if TYPE_CHECKING:",
101
+ "if __name__ == .__main__.:",
102
+ "\\.\\.\\.",
103
+ ]
104
+
105
+ [tool.ruff]
106
+ target-version = "py310"
107
+ line-length = 100
108
+
109
+ [tool.ruff.lint]
110
+ select = [
111
+ "E", # pycodestyle errors
112
+ "W", # pycodestyle warnings
113
+ "F", # pyflakes
114
+ "I", # isort
115
+ "B", # flake8-bugbear
116
+ "C4", # flake8-comprehensions
117
+ "UP", # pyupgrade
118
+ "SIM", # flake8-simplify
119
+ ]
120
+ ignore = []
121
+
122
+ [tool.ruff.lint.flake8-bugbear]
123
+ extend-immutable-calls = ["fastapi.Depends", "fastapi.params.Depends"]
124
+
125
+ [tool.mypy]
126
+ python_version = "3.10"
127
+ strict = true
128
+ warn_return_any = true
129
+ warn_unused_configs = true
130
+ disallow_untyped_defs = true
131
+ disallow_incomplete_defs = true
132
+ check_untyped_defs = true
133
+ no_implicit_optional = true
134
+ show_error_codes = true