clear-skies 2.0.14__py3-none-any.whl → 2.0.16__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.

Potentially problematic release.


This version of clear-skies might be problematic. Click here for more details.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clear-skies
3
- Version: 2.0.14
3
+ Version: 2.0.16
4
4
  Summary: A framework for building backends in the cloud
5
5
  Project-URL: Documentation, https://clearskies.io/
6
6
  Project-URL: Repository, https://github.com/clearskies-py/clearskies
@@ -5,10 +5,10 @@ clearskies/configurable.py,sha256=gfX9o5qgMqc8lSzrdcUyR3b6zdOvg9ccYBQ0VvZjXkk,30
5
5
  clearskies/decorators.py,sha256=lcXJC4xI-hRyKDSH8yklcWjOrIL9k2Qks1xP2lmyDm0,1024
6
6
  clearskies/decorators.pyi,sha256=qSRzPJYYoV9trEsh_V1BxP2HdMz0G2gOs4FV8f5hvyU,388
7
7
  clearskies/end.py,sha256=mEPdBB4lh9zmAKTbsffCh-mQMZGIVohriWjm-952EzA,10629
8
- clearskies/endpoint.py,sha256=z4ys46jZC1rFSAfwdc-eScUDThcJ4mILRCQMcqvAX68,47960
8
+ clearskies/endpoint.py,sha256=Q_ovFPRB_8dRm2bU-yDHtXqeAVRVenILMD4f2wrtaKU,47947
9
9
  clearskies/endpoint_group.py,sha256=qsxQpt1i6IRvQqhQkt_udoVj0TMdoIOccvKyEBaeaEg,12343
10
10
  clearskies/environment.py,sha256=BbNgQH3uuCTxoHeLB9O1_HsPTaJL5aiXqY6hZ9aj-jo,3739
11
- clearskies/model.py,sha256=1cCx1KcAOK6_MHBdgtWdu4lZMYuPQaWHSrXsdW4v7V8,77545
11
+ clearskies/model.py,sha256=OBPIatlGpyoiIG0krdUy10icmouz6jLhdr81FtyH9Zo,77535
12
12
  clearskies/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  clearskies/schema.py,sha256=9S0RuFBiydsDy4kATy2BBsXJ9aWHILW0ja_q9F4kxb0,2872
14
14
  clearskies/security_header.py,sha256=_RsQEJahVTIB8m8IIgQgYk8NhX_6QJqRJpQDh2NETNo,467
@@ -19,7 +19,7 @@ clearskies/authentication/__init__.py,sha256=MxXNCWhKbha7TPu_MAyssfTdOCEDSNBwzsh
19
19
  clearskies/authentication/authentication.py,sha256=B1I8udvtGfEdiUrqUM8V3YT_Cxema9eDOSlnXjgC35s,1230
20
20
  clearskies/authentication/authorization.py,sha256=87eRORyR7RpyB5YnLm6zqn4JQjTUIA4psfTjTE-oSSg,805
21
21
  clearskies/authentication/authorization_pass_through.py,sha256=EEQ-JJbBVLAoRefrNFAWBicoJO5k3B4gZQc2rQAwIBk,556
22
- clearskies/authentication/jwks.py,sha256=_-peGZC9vDcIxuPXFObvIGX_GA04aOfewVNngrdbCDA,4857
22
+ clearskies/authentication/jwks.py,sha256=slAx3xbTDiIWx0Cp7fn4z7_iDfGMWZZ-YAHHX5Imae0,4852
23
23
  clearskies/authentication/public.py,sha256=GSNl4X4fnB25BZoXSo8nqL0iZCa9rzfvPfIsJ2Y34B4,84
24
24
  clearskies/authentication/secret_bearer.py,sha256=OVLi9kJNIGF1Cyl4nOxDxuuctZCVBP2L-bT2Og8qCHE,17377
25
25
  clearskies/autodoc/__init__.py,sha256=JRUAmd0he8iGlgiZvxewLMIXJqnOFEdvlaKAtHpC2lo,124
@@ -29,7 +29,7 @@ clearskies/autodoc/formats/oai3_json/__init__.py,sha256=tbbOZWkX9ZWj4BM3arHrlmqy
29
29
  clearskies/autodoc/formats/oai3_json/oai3_json.py,sha256=-LViw86zpPAgAEnC42KuobccvFATRg-j8ZEd8BiTYFA,2964
30
30
  clearskies/autodoc/formats/oai3_json/oai3_schema_resolver.py,sha256=5gifJ36dyWEeYtfjHVbbTpPBo0BB1Gqxt0Y3sxTiHJA,509
31
31
  clearskies/autodoc/formats/oai3_json/parameter.py,sha256=h9bHXxqJhUc7NRQCZF6RnIPuaY9BA6V_xzYNnsplXlc,1110
32
- clearskies/autodoc/formats/oai3_json/request.py,sha256=WHEWQvhuhkw82V4YS6GwDN4y8Qy7QDSn9awJEhwLmWU,2939
32
+ clearskies/autodoc/formats/oai3_json/request.py,sha256=RM6PgdZNHVP6iH9oeOfSPwyp-v0k3MhUEOT8SLxORd0,2932
33
33
  clearskies/autodoc/formats/oai3_json/response.py,sha256=ou06oFQtaAR70qIvIoAe4QzohWiACzhCwlW73oM5Dvg,778
34
34
  clearskies/autodoc/formats/oai3_json/test.json,sha256=DdMvSUbaTEAyWtX_RDxEFR82kK9pCCTeFUghQwHjB3s,59848
35
35
  clearskies/autodoc/formats/oai3_json/schema/__init__.py,sha256=VJiDueMdGfJoVQVt9SXIE_-uPghSXtCzpTXuqPaaiRw,173
@@ -62,15 +62,15 @@ clearskies/autodoc/schema/password.py,sha256=hSXPvHoXEbG-KHQFxXubEarxSMg9Cki_n8t
62
62
  clearskies/autodoc/schema/schema.py,sha256=zsJFtEyUCGGokYsnpcIfRVbeEwVTOWqE6VjTYyv8JZM,242
63
63
  clearskies/autodoc/schema/string.py,sha256=GXRI-aU8PYmjfnhmfaOe4vq7JASb-aB4SiFeG-EmJY0,60
64
64
  clearskies/backends/__init__.py,sha256=krBB3gHLP-lVYkm5ksdK7teEtouAHhL3EC__WGVnF4A,3157
65
- clearskies/backends/api_backend.py,sha256=4xcAymjkAgIA_9H68owe2Y9D4omxRnq6tnp_0RTIEhc,54133
65
+ clearskies/backends/api_backend.py,sha256=yOiPgLV4M4zuAYK3IikZlaCmJb0wUlzjwdo1zTQ24I4,54665
66
66
  clearskies/backends/backend.py,sha256=XzFBsUP4lwX2c2_zeK4Hch1MlT3YJS1ffxolUHoJXqA,5797
67
67
  clearskies/backends/cursor_backend.py,sha256=5YBO0EwxU_1YKIL3_fIbA93sh7NG4Qg8jpAMoIA5qiU,14139
68
68
  clearskies/backends/memory_backend.py,sha256=H_2fib9EFdXsg3ZMMpC20DMHnrnYDbPgZnmiarbOhiM,33963
69
- clearskies/backends/secrets_backend.py,sha256=6YVx154vhFLt_Fz0dz8wjQiVbaqBzPoUlfsYXU-9h7s,4044
69
+ clearskies/backends/secrets_backend.py,sha256=f_C5oAAr3tgM4UqioYPWcASPe9DhySC_uLWYGgMEPpY,3987
70
70
  clearskies/columns/__init__.py,sha256=a__-1hv-aMV3RU0Sd-BEkfItSJaG51EF2VeRQoTdka8,1990
71
71
  clearskies/columns/audit.py,sha256=KABjKk3YdV6G_43OdkhFA_iGkmjP9Sb-m0Beh2_aXU4,7624
72
72
  clearskies/columns/belongs_to_id.py,sha256=Ga3IpWlMy2_m8e5OK_iortNjHdMbF1RQF2tglWAzBVc,17575
73
- clearskies/columns/belongs_to_model.py,sha256=nZ-yOs5CJx_WoMQ2wLLQfwSTfuF5vantEL0DFUgwC4Q,5714
73
+ clearskies/columns/belongs_to_model.py,sha256=6DonRb1JSAlCjHnaSnZ92K9r0WrNNWhUIH_mN1tcRCE,5708
74
74
  clearskies/columns/belongs_to_self.py,sha256=cmgjxq4SmokGO2UbE0VlcFRXack9KjPLzyE9L3fNang,3725
75
75
  clearskies/columns/boolean.py,sha256=pdkO7dxqIYCHX95C_yGo5vyvH_D0fO8zs0XgRN50zMQ,3713
76
76
  clearskies/columns/category_tree.py,sha256=hqMlYQjVRlsU0PsC_M3_WWKkkzqw8wM5Xo-D4Mp9tIc,10967
@@ -100,10 +100,10 @@ clearskies/columns/phone.py,sha256=AVNeNXm_A_CjD4W-QeJtsKHMIlMQc_DbpKFDxJKw9H4,5
100
100
  clearskies/columns/select.py,sha256=Huef3sp9JP2DRzXgNBurZfY4lsKn0RU4WmAj689HlWw,2714
101
101
  clearskies/columns/string.py,sha256=Vyl1eb6RjW8q0a4AMqHI01vBLao9f7fkowNUumNoPqU,2594
102
102
  clearskies/columns/timestamp.py,sha256=nIEbvg1YqKPjtEeFyYRnPPPSYB_lYIIUUm8zNoE8dE8,5810
103
- clearskies/columns/updated.py,sha256=BFan3JnO2IEbryTGC2rR_RD1ruDcev49owPBYyjjSVI,3340
103
+ clearskies/columns/updated.py,sha256=qE9CGwTwURGp9hr4zQAW8inpp-Xz2leWsIiHHcG1Ao4,3324
104
104
  clearskies/columns/uuid.py,sha256=QE1UKHA9zt7bYd59rYRmzIHSonq9-sZeQbAIQtoJC54,2265
105
105
  clearskies/configs/README.md,sha256=4-r2FvkrBTrKkcKgJ5O3Qj1RZ7nnkknenKze4XYlQDs,4827
106
- clearskies/configs/__init__.py,sha256=dCuGWN6eI7r9hW8d33R4nCehEMdgEpvJU1TQ-NWVK6M,5401
106
+ clearskies/configs/__init__.py,sha256=DwpoecIXXFzQMHCi38pohYHSbw7KIb6z0hSkus2HKGg,5385
107
107
  clearskies/configs/actions.py,sha256=5OwrokU8uTSSQ_6SvL94SOP5JVkvRRFGAXNcCdMt8aQ,1388
108
108
  clearskies/configs/any.py,sha256=QSLOO955Lbg8NqYeyxdQGXTTyfFc5P036LORUa7avHc,388
109
109
  clearskies/configs/any_dict.py,sha256=LECTIcCF22JXbAaZdWSmKh9UShRuRt8PydNCuj05ijI,907
@@ -120,13 +120,13 @@ clearskies/configs/datetime.py,sha256=QJxqRyFkb0YByHmaH_Rd_geUiyvBpk5xdBdRDj2827
120
120
  clearskies/configs/datetime_or_callable.py,sha256=hp6ay-958DWoPy8Ryf1VS4R5NPKoF9LceiUhSB7I_wg,835
121
121
  clearskies/configs/email.py,sha256=BbXGvZnO9wwT8LHexAq0ibwDNLVvv_8yUJEOThzJVE4,317
122
122
  clearskies/configs/email_list.py,sha256=cTgdQTz4HYkqbdTEHPy8LcLjPGqFWY5TOIH8cHbfXXI,582
123
- clearskies/configs/email_list_or_callable.py,sha256=jowDly4ZKLOYJ73aJ8VoNX338jzqTZyIcY91ANvrgt0,679
123
+ clearskies/configs/email_list_or_callable.py,sha256=iApQZzHEy6Pn5XiZzRn2gbHkRipIdLVqXzmwkjiMdmI,650
124
124
  clearskies/configs/email_or_email_list_or_callable.py,sha256=tFdAsI1sTDMOheb3h8nQhIVxnl9xzZPwZtKjYEHjkKM,2470
125
125
  clearskies/configs/endpoint.py,sha256=NEDthtdPzejAot7yzUjC01PvQJR9BIyk5YnWXCi1w9I,759
126
126
  clearskies/configs/endpoint_list.py,sha256=HS1IO2HX8Y0W5ZZU7_Yk_6p5a8mo93an5Q2KAkOl9ZU,1202
127
127
  clearskies/configs/float.py,sha256=7HwDMf-3VfrZxTmXwpnwDgXyzujUBpz1xPi1StdjB1Q,621
128
128
  clearskies/configs/float_or_callable.py,sha256=9IiylL4Gg9_7HJOrYxbUPuLGE03TwKsAMsxfB7Lh2yY,744
129
- clearskies/configs/headers.py,sha256=D3bo3jE8x5DA1vLeo9ewnfIBHcRbr0JavOY-SQyFeVQ,986
129
+ clearskies/configs/headers.py,sha256=MY_oYm4tI5_9h635E8Yo_hj2id5IqfztqtwRZVdYaYo,976
130
130
  clearskies/configs/integer.py,sha256=lw05RhD8ZkHO_tYJLtCUHZ_Ucz2Mf7C0Z5wVOsMqgq0,620
131
131
  clearskies/configs/integer_or_callable.py,sha256=acCUP2ZSfSMPyID2LzIOQ-dlgARpxEktgr7KFWMtGbk,739
132
132
  clearskies/configs/joins.py,sha256=i1QmxFwkpL-pnzVPh3mrHpwrvzsjt9nH5pMSj4J1TT4,944
@@ -157,13 +157,13 @@ clearskies/configs/writeable_model_column.py,sha256=22pMoOAwYjvhHBcFrBb6Imtuoahb
157
157
  clearskies/configs/writeable_model_columns.py,sha256=vQFh5w6ToC8SDi_GaEvy33csp2CTFIroAfOLigHjFKo,359
158
158
  clearskies/contexts/__init__.py,sha256=f7XVUq2UKlDH6fjmcUWk6lbe9p_OaGpZ5ZjM6CuwTGQ,247
159
159
  clearskies/contexts/cli.py,sha256=cuGWoyRhHlO_Ba6Dozg3sGob1VZoI4TBFOLu-2Udabk,2838
160
- clearskies/contexts/context.py,sha256=rT-d0v5wiVqRNz_bsitTBXYEy0555-H2xr9TpETf-og,3676
161
- clearskies/contexts/wsgi.py,sha256=Wrf0B9WxoMPe71jn2fATsSYyS_Ego3VKFGjuI6KliWs,3165
162
- clearskies/contexts/wsgi_ref.py,sha256=q78gyeQS3KJ80NsozJkKb0ag00_6uwPK1yj5wxUM3JA,2818
160
+ clearskies/contexts/context.py,sha256=RFIJbpP32iv0NuvepCNldrFRYMWTbGssM_nduBDJLh8,3640
161
+ clearskies/contexts/wsgi.py,sha256=gS6eJxtDsae2sFNP3v7lhFqK5KfVTHjs9uGYqKS63Mw,3131
162
+ clearskies/contexts/wsgi_ref.py,sha256=aFJ40hqAwvYcftXESMvJz5W58c2qWK3BUYeksEMi5KU,2770
163
163
  clearskies/di/__init__.py,sha256=Ab8GNv9ZksnCABq8n2gCcyLEAXD-5-kX4O8PweTJIFs,474
164
164
  clearskies/di/additional_config.py,sha256=65INxw8aqTZQsyaKPj-aQmd6FBe4_4DwibXGgWYBy14,5139
165
165
  clearskies/di/additional_config_auto_import.py,sha256=XYw0Kcnp6hp-ee-c0YjiATwJvRb2E82xk9PuoX9dGRY,758
166
- clearskies/di/di.py,sha256=_H3K5BK_kkY-8PP7GA5w2i0BmG4EX4nwQLot_TCjc7w,46416
166
+ clearskies/di/di.py,sha256=gjyj5fudA9M2JB1_kl_GTn2yH4SaF6M32kR7Lz5Hfz4,46395
167
167
  clearskies/di/injectable.py,sha256=TTgqhx494470I61-88BUQmHmevfat-wXVseKl8pQOEk,852
168
168
  clearskies/di/injectable_properties.py,sha256=yJP0J7l7tjG2soyXtrfDgktE7M8tQHaP-55Cmtq0b7M,6466
169
169
  clearskies/di/inject/__init__.py,sha256=plEkWId-VyhvqX5KM2HhdCqi7_ZJzPmFz69cPAo812Y,643
@@ -172,14 +172,14 @@ clearskies/di/inject/by_class.py,sha256=1wn08Ahne1nJ-ddRRE4i70U2XwCvU_khG2U0iEGo
172
172
  clearskies/di/inject/by_name.py,sha256=Vgt_4NdptIVNrpVawGz-ZZfqp1MQLnvlqAZmjsX0WqI,675
173
173
  clearskies/di/inject/di.py,sha256=wuJU7u3AKPYoymQVcIR8m7t4pVIEtMvsN1RzujMqGfk,311
174
174
  clearskies/di/inject/environment.py,sha256=gQ1Tf2OVpcBNB3ciTv44rc7sKZM3pIOkbCFsCj0ELEI,469
175
- clearskies/di/inject/input_output.py,sha256=URb2qt8F-0QJ1zQpGdkrJxrZVNyF7S21EhhE5x2Irys,517
175
+ clearskies/di/inject/input_output.py,sha256=bpHuqomGmpHzQwgekbX8kYxeUfEPEaOCX4xp4ryXOa8,500
176
176
  clearskies/di/inject/now.py,sha256=Kp4xkRfOKAf4vl0hwo0PspKbfDxbhfptMm1rrXgc__0,395
177
177
  clearskies/di/inject/requests.py,sha256=ZXeEihj76dli4sf-WfW-sEZ30Y63eUqnP4OPChbovt4,403
178
178
  clearskies/di/inject/secrets.py,sha256=WDcu2Fg9QuBkIbl1lhT1j7L1JxOfl4oipJPLD3H_wyM,445
179
179
  clearskies/di/inject/utcnow.py,sha256=ugXgCerskwM9Pmc9OsdUKG4shbsYE-5c0YebUFx7ngQ,401
180
180
  clearskies/di/inject/uuid.py,sha256=GwMKqY-k7iDgc3QuOOe80aUejoU9PfFFyxZjl6Vinjc,408
181
- clearskies/di/test_module/__init__.py,sha256=7YHQF7JHP0FdI7GdEGANSZ_t1EISQYhUNm1wqOg0NKw,88
182
- clearskies/di/test_module/module_class.py,sha256=I_-wnMuHfbsvti-7d2Z4bXnr6deo__uvww9nds9qrlE,46
181
+ clearskies/di/test_module/__init__.py,sha256=UiuP3b8dbatcqOsVGyZ9vEPiNpr-IKJkp6PDXetHTvM,140
182
+ clearskies/di/test_module/module_class.py,sha256=cBF95A9616CTSx3P5GhR8-3201ttxIudYaWjxZD6apE,28
183
183
  clearskies/di/test_module/another_module/__init__.py,sha256=8SRmHPDepLKGWTUSc1ucDF6U8mJPsNDsBDmBQCpzPWo,35
184
184
  clearskies/endpoints/__init__.py,sha256=payWNEivwmxsT-pWqNkzHisSbyNjB7oq7_I5QIQL_XA,750
185
185
  clearskies/endpoints/advanced_search.py,sha256=FXbY1-VBf9qtsYAvXaqxLpR1FNUFhfB5EhhIx6fVDHk,21397
@@ -203,17 +203,18 @@ clearskies/exceptions/moved_permanently.py,sha256=fcgU_VBtAe8ZnbyNoNpXDcTQ8Utsjd
203
203
  clearskies/exceptions/moved_temporarily.py,sha256=Pt3muYHASvgOC50wPmoul9hUfy3Ud_NPSGFxshNWbIk,110
204
204
  clearskies/exceptions/not_found.py,sha256=_lZwovDrd18dUHDop5pF4mhexBPNr126xF2gOLA2-EA,36
205
205
  clearskies/functional/__init__.py,sha256=yXnbX-pjW6MOaBTjIzogvSJZ6O9dbUAWOalhu0WSDiQ,106
206
+ clearskies/functional/json.py,sha256=gKyLl_DNfSv1XddTQH6HtdOjqrhUXaRs_uImTh0Lei0,1594
206
207
  clearskies/functional/routing.py,sha256=tfIvP_Y29GTGr91_1ec3LSQFoTRwpkqU4BYHXPnBaXA,3685
207
208
  clearskies/functional/string.py,sha256=ZnkOjx8nxqZq2TV0CIb-Kz4onGoyekTX_WkLJM6XTmM,3311
208
209
  clearskies/functional/validations.py,sha256=cPYOTwWomlQrPvqPP_Jdlds7zZ5H9GABCP5pnGzC9T4,2821
209
210
  clearskies/input_outputs/__init__.py,sha256=9qeKJULw3MQ3zqkgBZice5d7qqRgsP3y-wkhWO2Y9vM,362
210
211
  clearskies/input_outputs/cli.py,sha256=t7uWqLi6VI3i_zuyoKLdIq3vUwr19lQZoJmuAxVEvgg,5741
211
212
  clearskies/input_outputs/headers.py,sha256=AnyqI64kploPX7qiBfQCD9w8b2FYWVIuwaXVafbpIiM,2085
212
- clearskies/input_outputs/input_output.py,sha256=tJQVN3U3MX_jpwsXJ-g-K1cdqQwyuSarTjo3JOp7zQQ,5154
213
+ clearskies/input_outputs/input_output.py,sha256=iaWi6B4o2hvNqL6CmXIc1Fv4UJNfLVLn9uNDuqmnDA0,5120
213
214
  clearskies/input_outputs/programmatic.py,sha256=OCRq0M42cKZKgk4YAfJyTWo3T4jNRmnGmVr7zCTovpg,1658
214
215
  clearskies/input_outputs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
215
- clearskies/input_outputs/wsgi.py,sha256=wcqZUu8zuKj9V1ur2oNlYqgcI_sC5LJEieZxvDVMMFU,2783
216
- clearskies/input_outputs/exceptions/__init__.py,sha256=3KiM3KaMYEKoToqCCQ4_no2n0W5ROqeBC0sI2Ix4P6w,82
216
+ clearskies/input_outputs/wsgi.py,sha256=qqU_3KeVt5oeZvqygQ2lSxkcmTCsGX7z0R8Zx1DVhag,2783
217
+ clearskies/input_outputs/exceptions/__init__.py,sha256=ONAtr46SecnF96TJkjWWJfVfSXWbJrOaAnkN-f6fKs4,137
217
218
  clearskies/input_outputs/exceptions/cli_input_error.py,sha256=kOFU8aLTLmeTL_AKDshxMu8_ufildg6p8ndhE1xHfb0,41
218
219
  clearskies/input_outputs/exceptions/cli_not_found.py,sha256=JBBuZA9ZwdkPhd3a0qaGgEPQrxh1fehy4R3ZaV2gWXU,39
219
220
  clearskies/query/__init__.py,sha256=ISF80_cG3rd574sRTdKKPxAdlSjtQh_ClXKKs_MSSSo,277
@@ -222,7 +223,7 @@ clearskies/query/join.py,sha256=4lrDUQzck7klKY_VYkc4SVK95SVwyy3SVTvasnsAEyc,4713
222
223
  clearskies/query/query.py,sha256=0XR3fNhOpDNJY0US2oseAS3p3Y0jxxVs86P6vWEvUcA,6063
223
224
  clearskies/query/sort.py,sha256=c-EtIkjg3kLjwSTdXD7sfyx-mNUhAepUV-2izprh3iY,754
224
225
  clearskies/secrets/__init__.py,sha256=G-A8YhCMlS_OdboSeKzCZp6iwfqwU4BPEnB5HvD88wY,142
225
- clearskies/secrets/akeyless.py,sha256=TuKJbi0LQYMsEAxMFFeNYopuM9otcX9ROToXkhVJGSk,20375
226
+ clearskies/secrets/akeyless.py,sha256=KFvehjTiWtl7YhOE3a99__F38N9IUQURNi-bkY7l8ZI,19348
226
227
  clearskies/secrets/secrets.py,sha256=z9ouvwTwdyyOFmaCCWMRR6T9capRWFHswz563OA-JzE,1566
227
228
  clearskies/secrets/additional_configs/__init__.py,sha256=cFCrbtKF5nuR061S2y1iKZp349x-y8Srdwe3VZbfSFU,1119
228
229
  clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py,sha256=CnIiXLVQdUnUey3dbCTXuNNP7Mmw1gjjNjZiBtfgGto,2757
@@ -237,7 +238,7 @@ clearskies/security_headers/csp.py,sha256=hms81Jw9VWzDRWdk5P7o3oq7LOOElpuGwhnIpw
237
238
  clearskies/security_headers/hsts.py,sha256=BeNrxxxrIWNxbF2Rb1fmOgmbF3rp1i5ve7iXh3Qr7q4,723
238
239
  clearskies/security_headers/x_content_type_options.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
239
240
  clearskies/security_headers/x_frame_options.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
240
- clearskies/validators/__init__.py,sha256=Hz0L5Y7EkeK4Px6WcdQ3ku6VqUGpLHX0ZWwCpT1ts1U,1248
241
+ clearskies/validators/__init__.py,sha256=v7TK6PlSjJxIuhx_aCoocBUCF-8DxNWWpYmoR7uOe6I,1247
241
242
  clearskies/validators/after_column.py,sha256=GqZTdwNlkkLYD5_UJExih5aOksMBKJ4Trvr56PhBPsk,2309
242
243
  clearskies/validators/before_column.py,sha256=jv5sUCeTwkkn-d1AFGaJccZdthc0o6rQASBT_vLHZbE,564
243
244
  clearskies/validators/in_the_future.py,sha256=xx2Du7iTsXWth5KWdyjnYb7iOYpFjjPxSZ1p69Ay54A,901
@@ -247,13 +248,13 @@ clearskies/validators/in_the_past.py,sha256=8eb79Q9feHL5rLsQdoOYIEsHegUiXI4zkH5S
247
248
  clearskies/validators/in_the_past_at_least.py,sha256=FT8rfs2-5Sd933Uql6-pwFRvvcPPXWq8hpobtkGr2z0,395
248
249
  clearskies/validators/in_the_past_at_most.py,sha256=AFJoIlA3xeoJtWKh-2-PG6A97_FMHwt4Yk3G9TRNLzA,393
249
250
  clearskies/validators/maximum_length.py,sha256=VxKvonpF58ng5icGt2d2BC2dWjXtNfnynjr95LZVYHg,843
250
- clearskies/validators/maximum_value.py,sha256=gqWRESL7rfPa4XYY2iDwjAu8NuVrtEwMXXMlY6rV_uk,871
251
- clearskies/validators/minimum_length.py,sha256=j-LHWLKXf3gF7yD9-RgNLXNm2gHj_-ZvGUxyCdRKPrw,860
252
- clearskies/validators/minimum_value.py,sha256=NDLcG6xCemlv3kfr-RiUaM3x2INS1GJGMB9RoOezZ7k,872
251
+ clearskies/validators/maximum_value.py,sha256=icdUN1AbT5c5SXpxDRks3954GRIUqu0FdpT6TeZFT2Q,855
252
+ clearskies/validators/minimum_length.py,sha256=2ukRKH35gdnjz9VezclIFCf3JtbN7iCbLSjlPNdaOyY,844
253
+ clearskies/validators/minimum_value.py,sha256=ZyG2S_-4lbbMbf7PUemEyAT-r4-gjJMUdEWccMam9H0,856
253
254
  clearskies/validators/required.py,sha256=GWxyexwj-K6DunZWNEnZxW6tQGAFd4oOCvQrW1s1K9k,1308
254
255
  clearskies/validators/timedelta.py,sha256=DJ0pTm-SSUtjZ7phGoD6vjb086vXPzvLLijkU-jQlOs,1892
255
- clearskies/validators/unique.py,sha256=GFEQOMYRIO9pSGHHj6zf1GdnJ0UM7Dm4ZO4uGn19BZo,991
256
- clear_skies-2.0.14.dist-info/METADATA,sha256=LEuwdzSsmZkbXo0VGjF8R9m7AIGOmbWW4CL3MCY_kPQ,2114
257
- clear_skies-2.0.14.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
258
- clear_skies-2.0.14.dist-info/licenses/LICENSE,sha256=3Ehd0g3YOpCj8sqj0Xjq5qbOtjjgk9qzhhD9YjRQgOA,1053
259
- clear_skies-2.0.14.dist-info/RECORD,,
256
+ clearskies/validators/unique.py,sha256=X7qGv_BfskNJWnYCt6vDHbvpBiHym58yLjXk5ZnhAlg,975
257
+ clear_skies-2.0.16.dist-info/METADATA,sha256=DWJ3EZbyG0Ny3gKospCLkq5xOx2znEJK-HDk4EUsLDM,2114
258
+ clear_skies-2.0.16.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
259
+ clear_skies-2.0.16.dist-info/licenses/LICENSE,sha256=3Ehd0g3YOpCj8sqj0Xjq5qbOtjjgk9qzhhD9YjRQgOA,1053
260
+ clear_skies-2.0.16.dist-info/RECORD,,
@@ -106,7 +106,7 @@ class Jwks(Authentication, di.InjectableProperties):
106
106
 
107
107
  def validate_jwt(self, raw_jwt):
108
108
  try:
109
- from jwcrypto import jwk, jws, jwt # type: ignore
109
+ from jwcrypto import jwk, jwt # type: ignore
110
110
  from jwcrypto.common import JWException # type: ignore
111
111
  except:
112
112
  raise ValueError(
@@ -1,6 +1,6 @@
1
1
  from typing import Any
2
2
 
3
- from ...schema import Array, Object
3
+ from ...schema import Object
4
4
  from .parameter import Parameter
5
5
  from .response import Response
6
6
 
@@ -11,6 +11,7 @@ from clearskies.autodoc.schema import Schema as AutoDocSchema
11
11
  from clearskies.autodoc.schema import String as AutoDocString
12
12
  from clearskies.backends.backend import Backend
13
13
  from clearskies.di import InjectableProperties, inject
14
+ from clearskies.functional import json as json_functional
14
15
  from clearskies.functional import routing, string
15
16
 
16
17
  if TYPE_CHECKING:
@@ -550,7 +551,7 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
550
551
  }
551
552
  ```
552
553
  """
553
- api_to_model_map = configs.StringDict(default={})
554
+ api_to_model_map = configs.AnyDict(default={})
554
555
 
555
556
  """
556
557
  The name of the pagination parameter
@@ -589,7 +590,7 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
589
590
  authentication: Authentication | None = None,
590
591
  model_casing: str = "snake_case",
591
592
  api_casing: str = "snake_case",
592
- api_to_model_map: dict[str, str] = {},
593
+ api_to_model_map: dict[str, str | list[str]] = {},
593
594
  pagination_parameter_name: str = "start",
594
595
  pagination_parameter_type: str = "str",
595
596
  limit_parameter_name: str = "limit",
@@ -897,16 +898,16 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
897
898
  f"The response from a records request returned a variable of type {response_data.__class__.__name__}, which is just confusing. To do automatic introspection, I need a list or a dictionary. I'm afraid you'll have to extend the API backend and override the map_record_response method to deal with this."
898
899
  )
899
900
 
900
- for key, value in response_data.items():
901
- if not isinstance(value, list):
902
- continue
903
- return self.map_records_response(value, query, query_data)
904
-
905
901
  # a records request may only return a single record, so before we fail, let's check for that
906
902
  record = self.check_dict_and_map_to_model(response_data, columns, query_data)
907
903
  if record is not None:
908
904
  return [record]
909
905
 
906
+ for key, value in response_data.items():
907
+ if not isinstance(value, list):
908
+ continue
909
+ return self.map_records_response(value, query, query_data)
910
+
910
911
  raise ValueError(
911
912
  "The response from a records request returned a dictionary, but none of the items in the dictionary was a list, so I don't know where to find the records. I only ever check one level deep in dictionaries. I'm afraid you'll have to extend the API backend and override the map_records_response method to deal with this."
912
913
  )
@@ -958,27 +959,38 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
958
959
  map_keys = set(response_to_model_map.keys())
959
960
  matching = response_keys.intersection(map_keys)
960
961
 
961
- # if nothing matches then clearly this isn't what we're looking for: repeat on all the children
962
- if not matching:
963
- for key, value in response_data.items():
964
- if not isinstance(value, dict):
965
- continue
966
- mapped = self.check_dict_and_map_to_model(value, columns)
967
- if mapped:
968
- return {**query_data, **mapped}
969
-
970
- # no match anywhere :(
971
- return None
972
-
973
962
  # we may need to be smarter about whether or not we think we found a match, but for now let's
974
963
  # ignore that possibility. If any columns match between the keys in our response dictionary and
975
964
  # the keys that we are expecting to find data in, then just assume that we have found a record.
976
965
  mapped = {response_to_model_map[key]: response_data[key] for key in matching}
977
966
 
967
+ for api_key, column_name in self.api_to_model_map.items():
968
+ if not "." in api_key:
969
+ continue
970
+ value = json_functional.get_nested_attribute(response_data, api_key)
971
+ if value is None:
972
+ continue
973
+ if isinstance(column_name, list):
974
+ for column in column_name:
975
+ mapped[column] = value
976
+ else:
977
+ mapped[column_name] = value
978
978
  # finally, move over anything not mentioned in the map
979
979
  for key in response_keys.difference(map_keys):
980
980
  mapped[string.swap_casing(key, self.api_casing, self.model_casing)] = response_data[key]
981
981
 
982
+ # if nothing matches then clearly this isn't what we're looking for: repeat on all the children
983
+ if not mapped:
984
+ for key, value in response_data.items():
985
+ if not isinstance(value, dict):
986
+ continue
987
+ remapped = self.check_dict_and_map_to_model(value, columns)
988
+ if remapped:
989
+ return {**query_data, **remapped}
990
+
991
+ # no match anywhere :(
992
+ return None
993
+
982
994
  return {**query_data, **mapped}
983
995
 
984
996
  def build_response_to_model_map(self, columns: dict[str, Column]) -> dict[str, str]:
@@ -7,7 +7,6 @@ from clearskies.query import Condition, Query
7
7
 
8
8
  if TYPE_CHECKING:
9
9
  from clearskies import Model
10
- from clearskies.authentication import Authentication
11
10
 
12
11
 
13
12
  class SecretsBackend(Backend):
@@ -65,7 +65,7 @@ class BelongsToModel(Column):
65
65
  parent_class = belongs_to_column.parent_model_class
66
66
  parent_model = self.di.build(parent_class, cache=False)
67
67
  if not parent_id:
68
- return parent_model.empty_model()
68
+ return parent_model.empty()
69
69
 
70
70
  parent_id_column_name = parent_model.id_column_name
71
71
  join_alias = belongs_to_column.join_table_alias()
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
5
  from clearskies import configs, decorators
@@ -63,8 +63,6 @@ class MyConfigurableClass(configs.Configurable):
63
63
 
64
64
  """
65
65
 
66
- import inspect
67
-
68
66
  from .actions import Actions
69
67
  from .any import Any
70
68
  from .any_dict import AnyDict
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Callable
4
-
5
3
  from clearskies.configs import string_list_or_callable
6
4
 
7
5
 
@@ -9,9 +9,7 @@ if TYPE_CHECKING:
9
9
 
10
10
 
11
11
  class Headers(config.Config):
12
- """
13
- This is for a configuration that should be an instance of type clearskies.input_outputs.Headers.
14
- """
12
+ """This is for a configuration that should be an instance of type clearskies.input_outputs.Headers."""
15
13
 
16
14
  def __set__(self, instance, value: headers.Headers):
17
15
  if value is None:
@@ -7,8 +7,7 @@ from typing import TYPE_CHECKING, Any, Callable
7
7
  from clearskies import exceptions
8
8
  from clearskies.di import Di
9
9
  from clearskies.di.additional_config import AdditionalConfig
10
- from clearskies.input_outputs import InputOutput
11
- from clearskies.input_outputs import Programmatic
10
+ from clearskies.input_outputs import InputOutput, Programmatic
12
11
 
13
12
  if TYPE_CHECKING:
14
13
  from clearskies.endpoint import Endpoint
@@ -1,7 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING
4
-
5
3
  from clearskies.contexts.context import Context
6
4
  from clearskies.input_outputs import Wsgi as WsgiInputOutput
7
5
 
@@ -4,7 +4,6 @@ import datetime
4
4
  from types import ModuleType
5
5
  from typing import TYPE_CHECKING, Any, Callable
6
6
  from wsgiref.simple_server import make_server
7
- from wsgiref.util import setup_testing_defaults
8
7
 
9
8
  from clearskies.contexts.context import Context
10
9
  from clearskies.input_outputs import Wsgi as WsgiInputOutput
clearskies/di/di.py CHANGED
@@ -1,8 +1,6 @@
1
1
  import datetime
2
2
  import inspect
3
3
  import os
4
- import re
5
- import sys
6
4
  from types import ModuleType
7
5
  from typing import Any, Callable
8
6
 
@@ -2,8 +2,6 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING
4
4
 
5
- import requests
6
-
7
5
  from clearskies.di.injectable import Injectable
8
6
 
9
7
  if TYPE_CHECKING:
@@ -4,3 +4,6 @@ from .module_class import ModuleClass
4
4
 
5
5
  class Hi:
6
6
  pass
7
+
8
+
9
+ __all__ = ["another_module", "ModuleClass", "Hi"]
@@ -1,5 +1,2 @@
1
- import datetime
2
-
3
-
4
1
  class ModuleClass:
5
2
  pass
clearskies/endpoint.py CHANGED
@@ -10,7 +10,7 @@ from clearskies.authentication import Authentication, Authorization, Public
10
10
  from clearskies.autodoc import schema
11
11
  from clearskies.autodoc.request import Parameter, Request
12
12
  from clearskies.autodoc.response import Response
13
- from clearskies.functional import routing, string, validations
13
+ from clearskies.functional import routing, string
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from clearskies import Column, Model, SecurityHeader
@@ -0,0 +1,47 @@
1
+ from typing import Any, cast
2
+
3
+
4
+ def get_nested_attribute(data: dict[str, Any] | str, attr_path: str) -> Any:
5
+ """
6
+ Extract a nested attribute from JSON data using dot notation.
7
+
8
+ This function navigates through a nested JSON structure using a dot-separated path
9
+ to retrieve a specific attribute. If the input is a string, it will attempt to parse
10
+ it as JSON first.
11
+
12
+ Example:
13
+ ```
14
+ data = {"database": {"credentials": {"username": "admin", "password": "secret"}}}
15
+ username = get_nested_attribute(data, "database.credentials.username")
16
+ # Returns "admin"
17
+ ```
18
+
19
+ Args:
20
+ data: The JSON data as a dictionary or a JSON string
21
+ attr_path: The path to the attribute using dot notation (e.g., "database.username")
22
+
23
+ Returns:
24
+ The value at the specified path
25
+
26
+ Raises:
27
+ ValueError: If the data cannot be parsed as JSON
28
+ KeyError: If the attribute path doesn't exist in the data
29
+ """
30
+ keys = attr_path.split(".", 1)
31
+ if not isinstance(data, dict):
32
+ try:
33
+ import json
34
+
35
+ data = json.loads(data)
36
+ except Exception:
37
+ raise ValueError(f"Could not parse data as JSON to get attribute '{attr_path}'")
38
+
39
+ # At this point, we know data is a dictionary
40
+ data_dict = cast(dict[str, Any], data) # Help type checker understand data is a dict
41
+
42
+ if len(keys) == 1:
43
+ if keys[0] not in data_dict:
44
+ raise KeyError(f"Data does not contain attribute '{attr_path}'")
45
+ return data_dict[keys[0]]
46
+
47
+ return get_nested_attribute(data_dict[keys[0]], keys[1])
@@ -1,2 +1,7 @@
1
1
  from .cli_input_error import CLIInputError
2
2
  from .cli_not_found import CLINotFound
3
+
4
+ __all__ = [
5
+ "CLIInputError",
6
+ "CLINotFound",
7
+ ]
@@ -3,7 +3,6 @@ from __future__ import annotations
3
3
  import json
4
4
  from abc import ABC, abstractmethod
5
5
  from typing import TYPE_CHECKING, Any
6
- from urllib.parse import parse_qs
7
6
 
8
7
  from clearskies import configs, configurable
9
8
 
@@ -1,8 +1,8 @@
1
1
  from __future__ import annotations
2
- from urllib.parse import parse_qs
3
2
 
4
3
  import json
5
4
  from typing import Callable
5
+ from urllib.parse import parse_qs
6
6
 
7
7
  from clearskies.input_outputs.headers import Headers
8
8
  from clearskies.input_outputs.input_output import InputOutput
clearskies/model.py CHANGED
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import re
4
3
  from abc import abstractmethod
5
4
  from typing import TYPE_CHECKING, Any, Callable, Iterator, Self
6
5
 
@@ -1,16 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import datetime
4
- import json
5
4
  import logging
6
5
  from types import ModuleType
7
6
  from typing import TYPE_CHECKING, Any
8
7
 
9
- from typing_extensions import override
10
-
11
8
  from clearskies import configs, secrets
12
9
  from clearskies.decorators import parameters_to_properties
13
10
  from clearskies.di import inject
11
+ from clearskies.functional.json import get_nested_attribute
14
12
  from clearskies.secrets.exceptions import PermissionsError
15
13
 
16
14
  if TYPE_CHECKING:
@@ -226,7 +224,7 @@ class Akeyless(secrets.Secrets):
226
224
  raise KeyError(f"Secret '{path}' not found")
227
225
  raise e
228
226
  if json_attribute:
229
- return self._get_nested_attribute(res[path], json_attribute) # type: ignore
227
+ return get_nested_attribute(res[path], json_attribute) # type: ignore
230
228
  return str(res[path])
231
229
 
232
230
  def get_dynamic_secret(
@@ -251,7 +249,7 @@ class Akeyless(secrets.Secrets):
251
249
  kwargs["args"] = args # type: ignore
252
250
  res: dict[str, Any] = self.api.get_dynamic_secret_value(self.akeyless.GetDynamicSecretValue(**kwargs)) # type: ignore
253
251
  if json_attribute:
254
- return self._get_nested_attribute(res, json_attribute)
252
+ return get_nested_attribute(res, json_attribute)
255
253
  return res
256
254
 
257
255
  def get_rotated_secret(
@@ -278,7 +276,7 @@ class Akeyless(secrets.Secrets):
278
276
 
279
277
  res: dict[str, str] = self._api.get_rotated_secret_value(self.akeyless.GetRotatedSecretValue(**kwargs))["value"] # type: ignore
280
278
  if json_attribute:
281
- return self._get_nested_attribute(res, json_attribute)
279
+ return get_nested_attribute(res, json_attribute)
282
280
  return res
283
281
 
284
282
  def describe_secret(self, path: str) -> Any:
@@ -472,26 +470,6 @@ class Akeyless(secrets.Secrets):
472
470
  self.akeyless.DescribePermissions(token=self._get_token(), path=path, type=type)
473
471
  ).client_permissions # type: ignore
474
472
 
475
- def _get_nested_attribute(self, data: dict[str, Any] | str, attr_path: str) -> Any:
476
- """
477
- Extract a nested attribute from JSON data.
478
-
479
- Parses the provided data as JSON if it's a string. Traverses the nested structure using
480
- the dot-separated path (e.g., "database.username"). Raises ValueError if the data cannot
481
- be parsed as JSON, or KeyError if the attribute path doesn't exist in the data.
482
- """
483
- keys = attr_path.split(".", 1)
484
- if not isinstance(data, dict):
485
- try:
486
- data = json.loads(data)
487
- except Exception:
488
- raise ValueError(f"Could not parse secret as JSON to get attribute '{attr_path}'")
489
- if len(keys) == 1:
490
- if not isinstance(data, dict) or keys[0] not in data:
491
- raise KeyError(f"Secret does not contain attribute '{attr_path}'")
492
- return data[keys[0]] # type: ignore
493
- return self._get_nested_attribute(data[keys[0]], keys[1]) # type: ignore
494
-
495
473
 
496
474
  class AkeylessSaml(Akeyless):
497
475
  """Convenience class for SAML authentication with Akeyless."""
@@ -25,8 +25,8 @@ __all__ = [
25
25
  "InThePastAtMost",
26
26
  "MaximumLength",
27
27
  "MaximumValue",
28
+ "MinimumValue",
28
29
  "MinimumLength",
29
- "MaximumLength",
30
30
  "Required",
31
31
  "Timedelta",
32
32
  "Unique",
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
5
  from clearskies import configs
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
5
  from clearskies import configs
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
5
  from clearskies import configs
@@ -1,6 +1,5 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
5
  from clearskies.validator import Validator