pytest-clerk 4.0.2__py3-none-any.whl → 4.0.4__py3-none-any.whl
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.
- pytest_clerk/clerk.py +40 -48
- {pytest_clerk-4.0.2.dist-info → pytest_clerk-4.0.4.dist-info}/METADATA +1 -1
- pytest_clerk-4.0.4.dist-info/RECORD +7 -0
- {pytest_clerk-4.0.2.dist-info → pytest_clerk-4.0.4.dist-info}/WHEEL +1 -1
- pytest_clerk-4.0.2.dist-info/RECORD +0 -7
- {pytest_clerk-4.0.2.dist-info → pytest_clerk-4.0.4.dist-info}/LICENSE +0 -0
- {pytest_clerk-4.0.2.dist-info → pytest_clerk-4.0.4.dist-info}/entry_points.txt +0 -0
pytest_clerk/clerk.py
CHANGED
|
@@ -7,15 +7,7 @@ import httpx
|
|
|
7
7
|
import pytest
|
|
8
8
|
from decouple import UndefinedValueError, config
|
|
9
9
|
from limits import RateLimitItemPerSecond, storage, strategies
|
|
10
|
-
from tenacity import retry,
|
|
11
|
-
|
|
12
|
-
retryable_status_codes = (
|
|
13
|
-
httpx.codes.TOO_MANY_REQUESTS,
|
|
14
|
-
httpx.codes.INTERNAL_SERVER_ERROR,
|
|
15
|
-
httpx.codes.BAD_GATEWAY,
|
|
16
|
-
httpx.codes.SERVICE_UNAVAILABLE,
|
|
17
|
-
httpx.codes.GATEWAY_TIMEOUT,
|
|
18
|
-
)
|
|
10
|
+
from tenacity import retry, stop_after_attempt, wait_random_exponential
|
|
19
11
|
|
|
20
12
|
logger = logging.getLogger(__name__)
|
|
21
13
|
|
|
@@ -32,31 +24,31 @@ class ClerkRateLimiter:
|
|
|
32
24
|
# limits.
|
|
33
25
|
self.no_limit = object()
|
|
34
26
|
self.backend_rate_limits = {
|
|
35
|
-
#
|
|
36
|
-
"POST": {r"/v1/users": RateLimitItemPerSecond(amount=
|
|
27
|
+
# 19 requests per 10 seconds.
|
|
28
|
+
"POST": {r"/v1/users": RateLimitItemPerSecond(amount=19, multiples=10)},
|
|
37
29
|
# No rate limits.
|
|
38
30
|
"GET": {r"/v1/jwks": self.no_limit},
|
|
39
|
-
#
|
|
40
|
-
"DEFAULT": RateLimitItemPerSecond(amount=
|
|
31
|
+
# 99 requests per 10 seconds.
|
|
32
|
+
"DEFAULT": RateLimitItemPerSecond(amount=99, multiples=10),
|
|
41
33
|
}
|
|
42
34
|
self.frontend_rate_limits = {
|
|
43
35
|
"POST": {
|
|
44
|
-
#
|
|
36
|
+
# 2 requests per 10 seconds.
|
|
45
37
|
r"/v1/client/sign_ins/(?P<sign_in_id>.*?)/attempt_first_factor": RateLimitItemPerSecond(
|
|
46
|
-
amount=
|
|
38
|
+
amount=2, multiples=10
|
|
47
39
|
),
|
|
48
|
-
#
|
|
40
|
+
# 2 requests per 10 seconds.
|
|
49
41
|
r"/v1/client/sign_ins/(?P<sign_in_id>.*?)/attempt_second_factor": RateLimitItemPerSecond(
|
|
50
|
-
amount=
|
|
42
|
+
amount=2, multiples=10
|
|
51
43
|
),
|
|
52
|
-
#
|
|
44
|
+
# 2 requests per 10 seconds.
|
|
53
45
|
r"/v1/client/sign_ups/(?P<sign_up_id>.*?)/attempt_verification": RateLimitItemPerSecond(
|
|
54
|
-
amount=
|
|
46
|
+
amount=2, multiples=10
|
|
55
47
|
),
|
|
56
|
-
#
|
|
57
|
-
r"/v1/client/sign_ins": RateLimitItemPerSecond(amount=
|
|
58
|
-
#
|
|
59
|
-
r"/v1/client/sign_ups": RateLimitItemPerSecond(amount=
|
|
48
|
+
# 4 requests per 10 seconds.
|
|
49
|
+
r"/v1/client/sign_ins": RateLimitItemPerSecond(amount=4, multiples=10),
|
|
50
|
+
# 4 requests per 10 seconds.
|
|
51
|
+
r"/v1/client/sign_ups": RateLimitItemPerSecond(amount=4, multiples=10),
|
|
60
52
|
}
|
|
61
53
|
}
|
|
62
54
|
self.storage = storage.MemoryStorage()
|
|
@@ -177,16 +169,6 @@ class ClerkRateLimiter:
|
|
|
177
169
|
sleep(1)
|
|
178
170
|
|
|
179
171
|
|
|
180
|
-
def retry_predicate(exception):
|
|
181
|
-
"""Return whether to retry. This depends on getting an exception with a response
|
|
182
|
-
object, and that response object having one of the status codes that we can retry.
|
|
183
|
-
"""
|
|
184
|
-
return (
|
|
185
|
-
hasattr(exception, "response")
|
|
186
|
-
and exception.response.status_code in retryable_status_codes
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
|
|
190
172
|
@pytest.fixture(scope="session")
|
|
191
173
|
def clerk_rate_limiter():
|
|
192
174
|
"""Return an instance of the Clerk rate limiter for use with HTTPX request hooks."""
|
|
@@ -234,6 +216,7 @@ def clerk_backend_httpx_client(clerk_secret_key, clerk_rate_limiter):
|
|
|
234
216
|
headers={"Authorization": f"Bearer {clerk_secret_key}"},
|
|
235
217
|
base_url="https://api.clerk.com/v1",
|
|
236
218
|
event_hooks={"request": [clerk_rate_limiter.rate_limit_hook]},
|
|
219
|
+
timeout=10,
|
|
237
220
|
)
|
|
238
221
|
|
|
239
222
|
yield client
|
|
@@ -268,7 +251,7 @@ def clerk_frontend_httpx_client(clerk_frontend_api_url, clerk_rate_limiter):
|
|
|
268
251
|
set via environment variables or in a .env file. This URL can be found under
|
|
269
252
|
Developers -> API Keys -> Show API URLs.
|
|
270
253
|
"""
|
|
271
|
-
with httpx.Client(base_url=f"{clerk_frontend_api_url}/v1") as client:
|
|
254
|
+
with httpx.Client(base_url=f"{clerk_frontend_api_url}/v1", timeout=10) as client:
|
|
272
255
|
result = client.post(url="/dev_browser")
|
|
273
256
|
|
|
274
257
|
result.raise_for_status()
|
|
@@ -277,6 +260,7 @@ def clerk_frontend_httpx_client(clerk_frontend_api_url, clerk_rate_limiter):
|
|
|
277
260
|
params={"__dev_session": result.json()["token"]},
|
|
278
261
|
base_url=f"{clerk_frontend_api_url}/v1",
|
|
279
262
|
event_hooks={"request": [clerk_rate_limiter.rate_limit_hook]},
|
|
263
|
+
timeout=10,
|
|
280
264
|
)
|
|
281
265
|
|
|
282
266
|
yield client
|
|
@@ -294,8 +278,9 @@ def clerk_delete_org(clerk_backend_httpx_client):
|
|
|
294
278
|
"""
|
|
295
279
|
|
|
296
280
|
@retry(
|
|
297
|
-
|
|
281
|
+
stop=stop_after_attempt(10),
|
|
298
282
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
283
|
+
reraise=True,
|
|
299
284
|
)
|
|
300
285
|
def _inner(org_id, **kwargs):
|
|
301
286
|
"""Delete the org with the given org ID. Any additional kwargs are passed
|
|
@@ -324,8 +309,9 @@ def clerk_create_org(clerk_backend_httpx_client, clerk_delete_org):
|
|
|
324
309
|
orgs_to_delete = []
|
|
325
310
|
|
|
326
311
|
@retry(
|
|
327
|
-
|
|
312
|
+
stop=stop_after_attempt(10),
|
|
328
313
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
314
|
+
reraise=True,
|
|
329
315
|
)
|
|
330
316
|
def _inner(organization_data, **kwargs):
|
|
331
317
|
"""This function creates an Organization with the provided organization_data,
|
|
@@ -337,8 +323,6 @@ def clerk_create_org(clerk_backend_httpx_client, clerk_delete_org):
|
|
|
337
323
|
The API documentation for this call can be found below:
|
|
338
324
|
https://clerk.com/docs/reference/backend-api/tag/Organizations#operation/CreateOrganization
|
|
339
325
|
"""
|
|
340
|
-
nonlocal orgs_to_delete
|
|
341
|
-
|
|
342
326
|
result = clerk_backend_httpx_client.post(
|
|
343
327
|
url="/organizations", json=organization_data, **kwargs
|
|
344
328
|
)
|
|
@@ -365,8 +349,9 @@ def clerk_update_org(clerk_backend_httpx_client):
|
|
|
365
349
|
"""
|
|
366
350
|
|
|
367
351
|
@retry(
|
|
368
|
-
|
|
352
|
+
stop=stop_after_attempt(10),
|
|
369
353
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
354
|
+
reraise=True,
|
|
370
355
|
)
|
|
371
356
|
def _inner(org_id_or_slug, organization_data, **kwargs):
|
|
372
357
|
"""This function attempts to update an organization with the provided
|
|
@@ -397,8 +382,9 @@ def clerk_get_org(clerk_backend_httpx_client):
|
|
|
397
382
|
"""
|
|
398
383
|
|
|
399
384
|
@retry(
|
|
400
|
-
|
|
385
|
+
stop=stop_after_attempt(10),
|
|
401
386
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
387
|
+
reraise=True,
|
|
402
388
|
)
|
|
403
389
|
def _inner(org_id_or_slug, **kwargs):
|
|
404
390
|
"""This function attempts to find and return the org with the given ID or slug.
|
|
@@ -428,8 +414,9 @@ def clerk_delete_user(clerk_backend_httpx_client):
|
|
|
428
414
|
"""
|
|
429
415
|
|
|
430
416
|
@retry(
|
|
431
|
-
|
|
417
|
+
stop=stop_after_attempt(10),
|
|
432
418
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
419
|
+
reraise=True,
|
|
433
420
|
)
|
|
434
421
|
def _inner(user_id, **kwargs):
|
|
435
422
|
"""Delete the user with the given user ID. All additional kwargs are passed
|
|
@@ -456,8 +443,9 @@ def clerk_create_user(clerk_backend_httpx_client, clerk_delete_user):
|
|
|
456
443
|
users_to_delete = []
|
|
457
444
|
|
|
458
445
|
@retry(
|
|
459
|
-
|
|
446
|
+
stop=stop_after_attempt(10),
|
|
460
447
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
448
|
+
reraise=True,
|
|
461
449
|
)
|
|
462
450
|
def _inner(user_data, **kwargs):
|
|
463
451
|
"""This function uses user_data to create a User with the backend API, and
|
|
@@ -469,7 +457,6 @@ def clerk_create_user(clerk_backend_httpx_client, clerk_delete_user):
|
|
|
469
457
|
The API documentation for this call can be found below:
|
|
470
458
|
https://clerk.com/docs/reference/backend-api/tag/Users#operation/CreateUser
|
|
471
459
|
"""
|
|
472
|
-
nonlocal users_to_delete
|
|
473
460
|
result = clerk_backend_httpx_client.post(url="/users", json=user_data, **kwargs)
|
|
474
461
|
result.raise_for_status()
|
|
475
462
|
result = result.json()
|
|
@@ -493,8 +480,9 @@ def clerk_add_org_member(clerk_backend_httpx_client):
|
|
|
493
480
|
"""
|
|
494
481
|
|
|
495
482
|
@retry(
|
|
496
|
-
|
|
483
|
+
stop=stop_after_attempt(10),
|
|
497
484
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
485
|
+
reraise=True,
|
|
498
486
|
)
|
|
499
487
|
def _inner(org_id, user_id, role, **kwargs):
|
|
500
488
|
"""Add's the provided user ID to the provided org ID with the provided role. All
|
|
@@ -527,8 +515,9 @@ def clerk_sign_user_in(clerk_frontend_httpx_client):
|
|
|
527
515
|
"""
|
|
528
516
|
|
|
529
517
|
@retry(
|
|
530
|
-
|
|
518
|
+
stop=stop_after_attempt(10),
|
|
531
519
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
520
|
+
reraise=True,
|
|
532
521
|
)
|
|
533
522
|
def _inner(email, password, **kwargs):
|
|
534
523
|
"""Attempts to sign in the user using the provided email and password, and then
|
|
@@ -565,8 +554,9 @@ def clerk_touch_user_session(clerk_frontend_httpx_client):
|
|
|
565
554
|
"""
|
|
566
555
|
|
|
567
556
|
@retry(
|
|
568
|
-
|
|
557
|
+
stop=stop_after_attempt(10),
|
|
569
558
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
559
|
+
reraise=True,
|
|
570
560
|
)
|
|
571
561
|
def _inner(session_id, session_data=None, **kwargs):
|
|
572
562
|
"""Given a Clerk user session ID and any optional session_data, touch the
|
|
@@ -626,8 +616,9 @@ def clerk_get_user_session_token(clerk_frontend_httpx_client):
|
|
|
626
616
|
"""
|
|
627
617
|
|
|
628
618
|
@retry(
|
|
629
|
-
|
|
619
|
+
stop=stop_after_attempt(10),
|
|
630
620
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
621
|
+
reraise=True,
|
|
631
622
|
)
|
|
632
623
|
def _inner(session_id, **kwargs):
|
|
633
624
|
"""Retrieves a currently valid session token for the user tied to the provided
|
|
@@ -659,8 +650,9 @@ def clerk_end_user_session(clerk_frontend_httpx_client):
|
|
|
659
650
|
"""
|
|
660
651
|
|
|
661
652
|
@retry(
|
|
662
|
-
|
|
653
|
+
stop=stop_after_attempt(10),
|
|
663
654
|
wait=wait_random_exponential(multiplier=0.5, max=60),
|
|
655
|
+
reraise=True,
|
|
664
656
|
)
|
|
665
657
|
def _inner(session_id, **kwargs):
|
|
666
658
|
"""Given a Clerk user session ID, ends that session. This passes through any
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
pytest_clerk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
pytest_clerk/clerk.py,sha256=hrLyb3IApqvx49U-7FsjuLMj_Cbtd17y71MpG89gu68,24621
|
|
3
|
+
pytest_clerk-4.0.4.dist-info/LICENSE,sha256=QLSYHsNt-ZLbbVtDs7h8o8v-V0SlK2BuGe7LmoPOasU,1064
|
|
4
|
+
pytest_clerk-4.0.4.dist-info/METADATA,sha256=OHo84IIKNcBJVHrsnbRZPL_D5VdZp9z1bThAwkVRFyw,1291
|
|
5
|
+
pytest_clerk-4.0.4.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
6
|
+
pytest_clerk-4.0.4.dist-info/entry_points.txt,sha256=ps5MgIGlDiWP4lufTAzoQhfwL-GA7rJquc1bqnVR-oA,44
|
|
7
|
+
pytest_clerk-4.0.4.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
pytest_clerk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
-
pytest_clerk/clerk.py,sha256=fjf4Io81i2grKuFE8AwzHd7X9vhjpet7rXTGVsCKhxQ,25203
|
|
3
|
-
pytest_clerk-4.0.2.dist-info/LICENSE,sha256=QLSYHsNt-ZLbbVtDs7h8o8v-V0SlK2BuGe7LmoPOasU,1064
|
|
4
|
-
pytest_clerk-4.0.2.dist-info/METADATA,sha256=I3IhRKapB-S3fpW44d60PewoMAidviBn9GNfIIT9yHs,1291
|
|
5
|
-
pytest_clerk-4.0.2.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
|
6
|
-
pytest_clerk-4.0.2.dist-info/entry_points.txt,sha256=ps5MgIGlDiWP4lufTAzoQhfwL-GA7rJquc1bqnVR-oA,44
|
|
7
|
-
pytest_clerk-4.0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|