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

Files changed (344) hide show
  1. {clear_skies-1.22.31.dist-info → clear_skies-2.0.0.dist-info}/METADATA +11 -13
  2. clear_skies-2.0.0.dist-info/RECORD +248 -0
  3. {clear_skies-1.22.31.dist-info → clear_skies-2.0.0.dist-info}/WHEEL +1 -1
  4. clearskies/__init__.py +42 -25
  5. clearskies/action.py +7 -0
  6. clearskies/authentication/__init__.py +8 -41
  7. clearskies/authentication/authentication.py +42 -0
  8. clearskies/authentication/authorization.py +4 -9
  9. clearskies/authentication/authorization_pass_through.py +11 -9
  10. clearskies/authentication/jwks.py +128 -58
  11. clearskies/authentication/public.py +3 -38
  12. clearskies/authentication/secret_bearer.py +516 -54
  13. clearskies/autodoc/formats/oai3_json/__init__.py +1 -1
  14. clearskies/autodoc/formats/oai3_json/oai3_json.py +9 -7
  15. clearskies/autodoc/formats/oai3_json/parameter.py +6 -3
  16. clearskies/autodoc/formats/oai3_json/request.py +7 -5
  17. clearskies/autodoc/formats/oai3_json/response.py +7 -4
  18. clearskies/autodoc/formats/oai3_json/schema/object.py +4 -1
  19. clearskies/autodoc/request/__init__.py +2 -0
  20. clearskies/autodoc/request/header.py +4 -6
  21. clearskies/autodoc/request/json_body.py +4 -6
  22. clearskies/autodoc/request/parameter.py +8 -0
  23. clearskies/autodoc/request/request.py +7 -4
  24. clearskies/autodoc/request/url_parameter.py +4 -6
  25. clearskies/autodoc/request/url_path.py +4 -6
  26. clearskies/autodoc/schema/__init__.py +4 -2
  27. clearskies/autodoc/schema/array.py +5 -6
  28. clearskies/autodoc/schema/boolean.py +4 -10
  29. clearskies/autodoc/schema/date.py +0 -3
  30. clearskies/autodoc/schema/datetime.py +1 -4
  31. clearskies/autodoc/schema/double.py +0 -3
  32. clearskies/autodoc/schema/enum.py +4 -2
  33. clearskies/autodoc/schema/integer.py +4 -9
  34. clearskies/autodoc/schema/long.py +0 -3
  35. clearskies/autodoc/schema/number.py +4 -9
  36. clearskies/autodoc/schema/object.py +5 -7
  37. clearskies/autodoc/schema/password.py +0 -3
  38. clearskies/autodoc/schema/schema.py +11 -0
  39. clearskies/autodoc/schema/string.py +4 -10
  40. clearskies/backends/__init__.py +55 -20
  41. clearskies/backends/api_backend.py +1100 -284
  42. clearskies/backends/backend.py +40 -84
  43. clearskies/backends/cursor_backend.py +236 -186
  44. clearskies/backends/memory_backend.py +519 -226
  45. clearskies/backends/secrets_backend.py +75 -31
  46. clearskies/column.py +1232 -0
  47. clearskies/columns/__init__.py +71 -0
  48. clearskies/columns/audit.py +205 -0
  49. clearskies/columns/belongs_to_id.py +483 -0
  50. clearskies/columns/belongs_to_model.py +128 -0
  51. clearskies/columns/belongs_to_self.py +105 -0
  52. clearskies/columns/boolean.py +109 -0
  53. clearskies/columns/category_tree.py +275 -0
  54. clearskies/columns/category_tree_ancestors.py +51 -0
  55. clearskies/columns/category_tree_children.py +127 -0
  56. clearskies/columns/category_tree_descendants.py +48 -0
  57. clearskies/columns/created.py +94 -0
  58. clearskies/columns/created_by_authorization_data.py +116 -0
  59. clearskies/columns/created_by_header.py +99 -0
  60. clearskies/columns/created_by_ip.py +92 -0
  61. clearskies/columns/created_by_routing_data.py +96 -0
  62. clearskies/columns/created_by_user_agent.py +92 -0
  63. clearskies/columns/date.py +230 -0
  64. clearskies/columns/datetime.py +278 -0
  65. clearskies/columns/email.py +76 -0
  66. clearskies/columns/float.py +149 -0
  67. clearskies/columns/has_many.py +505 -0
  68. clearskies/columns/has_many_self.py +56 -0
  69. clearskies/columns/has_one.py +14 -0
  70. clearskies/columns/integer.py +156 -0
  71. clearskies/columns/json.py +122 -0
  72. clearskies/columns/many_to_many_ids.py +333 -0
  73. clearskies/columns/many_to_many_ids_with_data.py +270 -0
  74. clearskies/columns/many_to_many_models.py +154 -0
  75. clearskies/columns/many_to_many_pivots.py +133 -0
  76. clearskies/columns/phone.py +158 -0
  77. clearskies/columns/select.py +91 -0
  78. clearskies/columns/string.py +98 -0
  79. clearskies/columns/timestamp.py +160 -0
  80. clearskies/columns/updated.py +110 -0
  81. clearskies/columns/uuid.py +86 -0
  82. clearskies/configs/README.md +105 -0
  83. clearskies/configs/__init__.py +159 -0
  84. clearskies/configs/actions.py +43 -0
  85. clearskies/configs/any.py +13 -0
  86. clearskies/configs/any_dict.py +22 -0
  87. clearskies/configs/any_dict_or_callable.py +23 -0
  88. clearskies/configs/authentication.py +23 -0
  89. clearskies/configs/authorization.py +23 -0
  90. clearskies/configs/boolean.py +16 -0
  91. clearskies/configs/boolean_or_callable.py +18 -0
  92. clearskies/configs/callable_config.py +18 -0
  93. clearskies/configs/columns.py +34 -0
  94. clearskies/configs/conditions.py +30 -0
  95. clearskies/configs/config.py +21 -0
  96. clearskies/configs/datetime.py +18 -0
  97. clearskies/configs/datetime_or_callable.py +19 -0
  98. clearskies/configs/endpoint.py +23 -0
  99. clearskies/configs/float.py +16 -0
  100. clearskies/configs/float_or_callable.py +18 -0
  101. clearskies/configs/integer.py +16 -0
  102. clearskies/configs/integer_or_callable.py +18 -0
  103. clearskies/configs/joins.py +30 -0
  104. clearskies/configs/list_any_dict.py +30 -0
  105. clearskies/configs/list_any_dict_or_callable.py +31 -0
  106. clearskies/configs/model_class.py +35 -0
  107. clearskies/configs/model_column.py +65 -0
  108. clearskies/configs/model_columns.py +56 -0
  109. clearskies/configs/model_destination_name.py +25 -0
  110. clearskies/configs/model_to_id_column.py +43 -0
  111. clearskies/configs/readable_model_column.py +9 -0
  112. clearskies/configs/readable_model_columns.py +9 -0
  113. clearskies/configs/schema.py +23 -0
  114. clearskies/configs/searchable_model_columns.py +9 -0
  115. clearskies/configs/security_headers.py +39 -0
  116. clearskies/configs/select.py +26 -0
  117. clearskies/configs/select_list.py +47 -0
  118. clearskies/configs/string.py +29 -0
  119. clearskies/configs/string_dict.py +32 -0
  120. clearskies/configs/string_list.py +32 -0
  121. clearskies/configs/string_list_or_callable.py +35 -0
  122. clearskies/configs/string_or_callable.py +18 -0
  123. clearskies/configs/timedelta.py +18 -0
  124. clearskies/configs/timezone.py +18 -0
  125. clearskies/configs/url.py +23 -0
  126. clearskies/configs/validators.py +45 -0
  127. clearskies/configs/writeable_model_column.py +9 -0
  128. clearskies/configs/writeable_model_columns.py +9 -0
  129. clearskies/configurable.py +76 -0
  130. clearskies/contexts/__init__.py +8 -8
  131. clearskies/contexts/cli.py +5 -42
  132. clearskies/contexts/context.py +78 -56
  133. clearskies/contexts/wsgi.py +13 -30
  134. clearskies/contexts/wsgi_ref.py +49 -0
  135. clearskies/di/__init__.py +10 -7
  136. clearskies/di/additional_config.py +115 -4
  137. clearskies/di/additional_config_auto_import.py +12 -0
  138. clearskies/di/di.py +742 -121
  139. clearskies/di/inject/__init__.py +23 -0
  140. clearskies/di/inject/by_class.py +21 -0
  141. clearskies/di/inject/by_name.py +18 -0
  142. clearskies/di/inject/di.py +13 -0
  143. clearskies/di/inject/environment.py +14 -0
  144. clearskies/di/inject/input_output.py +20 -0
  145. clearskies/di/inject/now.py +13 -0
  146. clearskies/di/inject/requests.py +13 -0
  147. clearskies/di/inject/secrets.py +14 -0
  148. clearskies/di/inject/utcnow.py +13 -0
  149. clearskies/di/inject/uuid.py +15 -0
  150. clearskies/di/injectable.py +29 -0
  151. clearskies/di/injectable_properties.py +131 -0
  152. clearskies/end.py +183 -0
  153. clearskies/endpoint.py +1309 -0
  154. clearskies/endpoint_group.py +297 -0
  155. clearskies/endpoints/__init__.py +23 -0
  156. clearskies/endpoints/advanced_search.py +526 -0
  157. clearskies/endpoints/callable.py +387 -0
  158. clearskies/endpoints/create.py +202 -0
  159. clearskies/endpoints/delete.py +139 -0
  160. clearskies/endpoints/get.py +275 -0
  161. clearskies/endpoints/health_check.py +181 -0
  162. clearskies/endpoints/list.py +573 -0
  163. clearskies/endpoints/restful_api.py +427 -0
  164. clearskies/endpoints/simple_search.py +286 -0
  165. clearskies/endpoints/update.py +190 -0
  166. clearskies/environment.py +5 -3
  167. clearskies/exceptions/__init__.py +17 -0
  168. clearskies/{handlers/exceptions/input_error.py → exceptions/input_errors.py} +1 -1
  169. clearskies/exceptions/moved_permanently.py +3 -0
  170. clearskies/exceptions/moved_temporarily.py +3 -0
  171. clearskies/exceptions/not_found.py +2 -0
  172. clearskies/functional/__init__.py +2 -2
  173. clearskies/functional/routing.py +92 -0
  174. clearskies/functional/string.py +19 -11
  175. clearskies/functional/validations.py +61 -9
  176. clearskies/input_outputs/__init__.py +9 -7
  177. clearskies/input_outputs/cli.py +130 -142
  178. clearskies/input_outputs/exceptions/__init__.py +1 -1
  179. clearskies/input_outputs/headers.py +45 -0
  180. clearskies/input_outputs/input_output.py +91 -122
  181. clearskies/input_outputs/programmatic.py +69 -0
  182. clearskies/input_outputs/wsgi.py +23 -38
  183. clearskies/model.py +489 -184
  184. clearskies/parameters_to_properties.py +31 -0
  185. clearskies/query/__init__.py +12 -0
  186. clearskies/query/condition.py +223 -0
  187. clearskies/query/join.py +136 -0
  188. clearskies/query/query.py +196 -0
  189. clearskies/query/sort.py +27 -0
  190. clearskies/schema.py +82 -0
  191. clearskies/secrets/__init__.py +3 -31
  192. clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py +15 -4
  193. clearskies/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +11 -5
  194. clearskies/secrets/akeyless.py +88 -147
  195. clearskies/secrets/secrets.py +8 -8
  196. clearskies/security_header.py +8 -0
  197. clearskies/security_headers/__init__.py +8 -8
  198. clearskies/security_headers/cache_control.py +47 -110
  199. clearskies/security_headers/cors.py +40 -95
  200. clearskies/security_headers/csp.py +76 -151
  201. clearskies/security_headers/hsts.py +14 -16
  202. clearskies/test_base.py +8 -0
  203. clearskies/typing.py +11 -0
  204. clearskies/validator.py +25 -0
  205. clearskies/validators/__init__.py +33 -0
  206. clearskies/validators/after_column.py +62 -0
  207. clearskies/validators/before_column.py +13 -0
  208. clearskies/validators/in_the_future.py +32 -0
  209. clearskies/validators/in_the_future_at_least.py +11 -0
  210. clearskies/validators/in_the_future_at_most.py +10 -0
  211. clearskies/validators/in_the_past.py +32 -0
  212. clearskies/validators/in_the_past_at_least.py +10 -0
  213. clearskies/validators/in_the_past_at_most.py +10 -0
  214. clearskies/validators/maximum_length.py +26 -0
  215. clearskies/validators/maximum_value.py +29 -0
  216. clearskies/validators/minimum_length.py +26 -0
  217. clearskies/validators/minimum_value.py +29 -0
  218. clearskies/validators/required.py +35 -0
  219. clearskies/validators/timedelta.py +59 -0
  220. clearskies/validators/unique.py +31 -0
  221. clear_skies-1.22.31.dist-info/RECORD +0 -214
  222. clearskies/application.py +0 -29
  223. clearskies/authentication/auth0_jwks.py +0 -118
  224. clearskies/authentication/auth_exception.py +0 -2
  225. clearskies/authentication/jwks_jwcrypto.py +0 -51
  226. clearskies/backends/api_get_only_backend.py +0 -48
  227. clearskies/backends/example_backend.py +0 -43
  228. clearskies/backends/file_backend.py +0 -48
  229. clearskies/backends/json_backend.py +0 -7
  230. clearskies/backends/restful_api_advanced_search_backend.py +0 -103
  231. clearskies/binding_config.py +0 -16
  232. clearskies/column_types/__init__.py +0 -203
  233. clearskies/column_types/audit.py +0 -249
  234. clearskies/column_types/belongs_to.py +0 -271
  235. clearskies/column_types/boolean.py +0 -60
  236. clearskies/column_types/category_tree.py +0 -304
  237. clearskies/column_types/column.py +0 -373
  238. clearskies/column_types/created.py +0 -26
  239. clearskies/column_types/created_by_authorization_data.py +0 -26
  240. clearskies/column_types/created_by_header.py +0 -24
  241. clearskies/column_types/created_by_ip.py +0 -17
  242. clearskies/column_types/created_by_routing_data.py +0 -25
  243. clearskies/column_types/created_by_user_agent.py +0 -17
  244. clearskies/column_types/created_micro.py +0 -26
  245. clearskies/column_types/datetime.py +0 -109
  246. clearskies/column_types/datetime_micro.py +0 -12
  247. clearskies/column_types/email.py +0 -18
  248. clearskies/column_types/float.py +0 -43
  249. clearskies/column_types/has_many.py +0 -179
  250. clearskies/column_types/has_one.py +0 -60
  251. clearskies/column_types/integer.py +0 -41
  252. clearskies/column_types/json.py +0 -25
  253. clearskies/column_types/many_to_many.py +0 -278
  254. clearskies/column_types/many_to_many_with_data.py +0 -162
  255. clearskies/column_types/phone.py +0 -48
  256. clearskies/column_types/select.py +0 -11
  257. clearskies/column_types/string.py +0 -24
  258. clearskies/column_types/timestamp.py +0 -73
  259. clearskies/column_types/updated.py +0 -26
  260. clearskies/column_types/updated_micro.py +0 -26
  261. clearskies/column_types/uuid.py +0 -25
  262. clearskies/columns.py +0 -123
  263. clearskies/condition_parser.py +0 -172
  264. clearskies/contexts/build_context.py +0 -54
  265. clearskies/contexts/convert_to_application.py +0 -190
  266. clearskies/contexts/extract_handler.py +0 -37
  267. clearskies/contexts/test.py +0 -94
  268. clearskies/decorators/__init__.py +0 -41
  269. clearskies/decorators/allow_non_json_bodies.py +0 -9
  270. clearskies/decorators/auth0_jwks.py +0 -22
  271. clearskies/decorators/authorization.py +0 -10
  272. clearskies/decorators/binding_classes.py +0 -9
  273. clearskies/decorators/binding_modules.py +0 -9
  274. clearskies/decorators/bindings.py +0 -9
  275. clearskies/decorators/create.py +0 -10
  276. clearskies/decorators/delete.py +0 -10
  277. clearskies/decorators/docs.py +0 -14
  278. clearskies/decorators/get.py +0 -10
  279. clearskies/decorators/jwks.py +0 -26
  280. clearskies/decorators/merge.py +0 -124
  281. clearskies/decorators/patch.py +0 -10
  282. clearskies/decorators/post.py +0 -10
  283. clearskies/decorators/public.py +0 -11
  284. clearskies/decorators/response_headers.py +0 -10
  285. clearskies/decorators/return_raw_response.py +0 -9
  286. clearskies/decorators/schema.py +0 -10
  287. clearskies/decorators/secret_bearer.py +0 -24
  288. clearskies/decorators/security_headers.py +0 -10
  289. clearskies/di/standard_dependencies.py +0 -151
  290. clearskies/handlers/__init__.py +0 -41
  291. clearskies/handlers/advanced_search.py +0 -271
  292. clearskies/handlers/base.py +0 -479
  293. clearskies/handlers/callable.py +0 -192
  294. clearskies/handlers/create.py +0 -35
  295. clearskies/handlers/crud_by_method.py +0 -18
  296. clearskies/handlers/database_connector.py +0 -32
  297. clearskies/handlers/delete.py +0 -61
  298. clearskies/handlers/exceptions/__init__.py +0 -5
  299. clearskies/handlers/exceptions/not_found.py +0 -3
  300. clearskies/handlers/get.py +0 -156
  301. clearskies/handlers/health_check.py +0 -59
  302. clearskies/handlers/input_processing.py +0 -79
  303. clearskies/handlers/list.py +0 -530
  304. clearskies/handlers/mygrations.py +0 -82
  305. clearskies/handlers/request_method_routing.py +0 -47
  306. clearskies/handlers/restful_api.py +0 -218
  307. clearskies/handlers/routing.py +0 -62
  308. clearskies/handlers/schema_helper.py +0 -128
  309. clearskies/handlers/simple_routing.py +0 -206
  310. clearskies/handlers/simple_routing_route.py +0 -197
  311. clearskies/handlers/simple_search.py +0 -136
  312. clearskies/handlers/update.py +0 -102
  313. clearskies/handlers/write.py +0 -193
  314. clearskies/input_requirements/__init__.py +0 -78
  315. clearskies/input_requirements/after.py +0 -36
  316. clearskies/input_requirements/before.py +0 -36
  317. clearskies/input_requirements/in_the_future_at_least.py +0 -19
  318. clearskies/input_requirements/in_the_future_at_most.py +0 -19
  319. clearskies/input_requirements/in_the_past_at_least.py +0 -19
  320. clearskies/input_requirements/in_the_past_at_most.py +0 -19
  321. clearskies/input_requirements/maximum_length.py +0 -19
  322. clearskies/input_requirements/maximum_value.py +0 -19
  323. clearskies/input_requirements/minimum_length.py +0 -22
  324. clearskies/input_requirements/minimum_value.py +0 -19
  325. clearskies/input_requirements/required.py +0 -23
  326. clearskies/input_requirements/requirement.py +0 -25
  327. clearskies/input_requirements/time_delta.py +0 -38
  328. clearskies/input_requirements/unique.py +0 -18
  329. clearskies/mocks/__init__.py +0 -7
  330. clearskies/mocks/input_output.py +0 -124
  331. clearskies/mocks/models.py +0 -142
  332. clearskies/models.py +0 -350
  333. clearskies/security_headers/base.py +0 -12
  334. clearskies/tests/simple_api/models/__init__.py +0 -2
  335. clearskies/tests/simple_api/models/status.py +0 -23
  336. clearskies/tests/simple_api/models/user.py +0 -21
  337. clearskies/tests/simple_api/users_api.py +0 -64
  338. {clear_skies-1.22.31.dist-info → clear_skies-2.0.0.dist-info}/LICENSE +0 -0
  339. /clearskies/{contexts/bash.py → autodoc/py.typed} +0 -0
  340. /clearskies/{handlers/exceptions → exceptions}/authentication.py +0 -0
  341. /clearskies/{handlers/exceptions → exceptions}/authorization.py +0 -0
  342. /clearskies/{handlers/exceptions → exceptions}/client_error.py +0 -0
  343. /clearskies/{tests/__init__.py → input_outputs/py.typed} +0 -0
  344. /clearskies/{tests/simple_api/__init__.py → py.typed} +0 -0
@@ -1,76 +1,62 @@
1
- from .base import Base
2
- from ..binding_config import BindingConfig
1
+ import clearskies.configs
2
+ import clearskies.parameters_to_properties
3
+ from clearskies.security_header import SecurityHeader
3
4
 
4
- numbers = [
5
- "max_age",
6
- "stale_if_error",
7
- "stale_while_revalidate",
8
- "s_maxage",
9
- ]
10
- bools = [
11
- "immutable",
12
- "must_understand",
13
- "no_cache",
14
- "no_store",
15
- "no_transform",
16
- "private",
17
- "public",
18
- "s_maxage",
19
- ]
20
5
 
6
+ class CacheControl(SecurityHeader):
7
+ max_age = clearskies.configs.Integer()
8
+ s_maxage = clearskies.configs.Integer()
9
+ stale_while_revalidate = clearskies.configs.Integer()
10
+ stale_if_error = clearskies.configs.Integer()
11
+ immutable = clearskies.configs.Boolean(default=False)
12
+ must_understand = clearskies.configs.Boolean(default=False)
13
+ no_cache = clearskies.configs.Boolean(default=False)
14
+ no_store = clearskies.configs.Boolean(default=False)
15
+ no_transform = clearskies.configs.Boolean(default=False)
16
+ private = clearskies.configs.Boolean(default=False)
17
+ public = clearskies.configs.Boolean(default=False)
21
18
 
22
- class CacheControl(Base):
23
- max_age = None
24
- no_cache = None
25
- no_store = None
26
- no_transform = None
27
- s_maxage = None
28
- must_understand = None
29
- private = None
30
- public = None
31
- immutable = None
32
- stale_while_revalidate = None
33
- stale_if_error = None
19
+ numbers: list[str] = [
20
+ "max_age",
21
+ "stale_if_error",
22
+ "stale_while_revalidate",
23
+ "s_maxage",
24
+ ]
25
+ bools: list[str] = [
26
+ "immutable",
27
+ "must_understand",
28
+ "no_cache",
29
+ "no_store",
30
+ "no_transform",
31
+ "private",
32
+ "public",
33
+ ]
34
34
 
35
- def __init__(self, environment):
36
- super().__init__(environment)
37
-
38
- def configure(
35
+ @clearskies.parameters_to_properties.parameters_to_properties
36
+ def __init__(
39
37
  self,
40
- no_cache=None,
41
- no_store=None,
42
- no_transform=None,
43
- max_age=None,
44
- s_maxage=None,
45
- must_revalidate=None,
46
- proxy_revalidate=None,
47
- must_understand=None,
48
- private=None,
49
- public=None,
50
- immutable=None,
51
- stale_while_revalidate=None,
52
- stale_if_error=None,
38
+ max_age: int | None = None,
39
+ s_maxage: int | None = None,
40
+ stale_while_revalidate: int | None = None,
41
+ stale_if_error: int | None = None,
42
+ immutable: bool = False,
43
+ must_understand: bool = False,
44
+ no_cache: bool = False,
45
+ no_store: bool = False,
46
+ no_transform: bool = False,
47
+ private: bool = False,
48
+ public: bool = False,
53
49
  ):
54
- self.max_age = max_age
55
- self.no_cache = no_cache
56
- self.no_store = no_store
57
- self.no_transform = no_transform
58
- self.s_maxage = s_maxage
59
- self.must_understand = must_understand
60
- self.private = private
61
- self.public = public
62
- self.immutable = immutable
63
- self.stale_while_revalidate = stale_while_revalidate
64
- self.stale_if_error = stale_if_error
50
+ self.finalize_and_validate_configuration()
65
51
 
66
52
  def set_headers_for_input_output(self, input_output):
67
53
  parts = []
68
- for variable_name in bools:
54
+ for variable_name in self.bools:
69
55
  value = getattr(self, variable_name)
70
56
  if not value:
71
57
  continue
72
58
  parts.append(variable_name.replace("_", "-"))
73
- for variable_name in numbers:
59
+ for variable_name in self.numbers:
74
60
  value = getattr(self, variable_name)
75
61
  if value is None:
76
62
  continue
@@ -78,53 +64,4 @@ class CacheControl(Base):
78
64
  parts.append(f"{key_name}={value}")
79
65
  if not parts:
80
66
  return
81
- input_output.set_header("cache-control", ", ".join(parts))
82
-
83
-
84
- # Use an explicity param list, even though long, so that Python can provide some input checking directly
85
- def cache_control(
86
- self,
87
- no_cache=None,
88
- no_store=None,
89
- no_transform=None,
90
- max_age=None,
91
- s_maxage=None,
92
- must_revalidate=None,
93
- proxy_revalidate=None,
94
- must_understand=None,
95
- private=None,
96
- public=None,
97
- immutable=None,
98
- stale_while_revalidate=None,
99
- stale_if_error=None,
100
- ):
101
- for variable_name in numbers:
102
- value = locals()[variable_name]
103
- if value is not None and type(value) != int:
104
- actual_type = type(value)
105
- raise ValueError(
106
- f"Invalid configuration value for cache control: {variable_name} should be an integer but instead is '{actual_type}'"
107
- )
108
- for variable_name in bools:
109
- value = locals()[variable_name]
110
- if value is not None and type(value) != bool:
111
- actual_type = type(value)
112
- raise ValueError(
113
- f"Invalid configuration value for cache control: {variable_name} should be True/False but instead is of type '{actual_type}'"
114
- )
115
- return BindingConfig(
116
- CacheControl,
117
- no_cache=no_cache,
118
- no_store=no_store,
119
- no_transform=no_transform,
120
- max_age=max_age,
121
- s_maxage=s_maxage,
122
- must_revalidate=must_revalidate,
123
- proxy_revalidate=proxy_revalidate,
124
- must_understand=must_understand,
125
- private=private,
126
- public=public,
127
- immutable=immutable,
128
- stale_while_revalidate=stale_while_revalidate,
129
- stale_if_error=stale_if_error,
130
- )
67
+ input_output.response_headers.add("cache-control", ", ".join(parts))
@@ -1,105 +1,50 @@
1
- from .base import Base
2
- from ..binding_config import BindingConfig
3
-
4
- lists = [
5
- "headers",
6
- "expose_headers",
7
- "methods",
8
- ]
9
-
10
-
11
- class CORS(Base):
12
- origin = None
13
- methods = None
14
- headers = None
15
- max_age = None
16
- credentials = None
17
- expose_headers = None
1
+ import clearskies.configs
2
+ import clearskies.parameters_to_properties
3
+ from clearskies.security_header import SecurityHeader
4
+
5
+
6
+ class Cors(SecurityHeader):
7
+ origin = clearskies.configs.String()
8
+ methods = clearskies.configs.StringList(default=[])
9
+ headers = clearskies.configs.StringList(default=[])
10
+ max_age = clearskies.configs.Integer(default=5)
11
+ credentials = clearskies.configs.Boolean(default=False)
12
+ expose_headers = clearskies.configs.StringList(default=[])
18
13
  is_cors = True
19
14
 
20
- def __init__(self, environment):
21
- super().__init__(environment)
22
-
23
- def configure(self, origin=None, methods=None, headers=None, max_age=None, credentials=None, expose_headers=None):
24
- self.origin = origin
25
- self.max_age = max_age
26
- self.credentials = credentials
27
- self.expose_headers = ", ".join(expose_headers) if type(expose_headers) == list else expose_headers
28
- self.set_methods(methods)
29
- self.set_headers(headers)
15
+ @clearskies.parameters_to_properties.parameters_to_properties
16
+ def __init__(
17
+ self,
18
+ credentials: bool = False,
19
+ expose_headers: list[str] = [],
20
+ headers: list[str] = [],
21
+ max_age: int = 5,
22
+ methods: list[str] = [],
23
+ origin: str = "",
24
+ ):
25
+ self.finalize_and_validate_configuration()
30
26
 
31
- def set_headers(self, headers):
32
- if type(headers) == list:
33
- headers = ", ".join(headers)
34
- self.headers = headers if headers is not None else ""
27
+ def set_headers(self, headers: list[str]):
28
+ self.headers = headers
35
29
 
36
- def add_header(self, header):
37
- if not self.headers:
38
- self.headers = header
39
- elif header not in self.headers:
40
- self.headers += ", " + header
30
+ def add_header(self, header: str):
31
+ self.headers = [*self.headers, header]
41
32
 
42
- def set_methods(self, methods):
43
- if type(methods) == list:
44
- methods = ", ".join(methods)
45
- self.methods = methods if methods is not None else ""
33
+ def set_methods(self, methods: list[str]):
34
+ self.methods = methods
46
35
 
47
- def add_method(self, method):
48
- if not self.methods:
49
- self.methods = method
50
- elif method not in self.methods:
51
- self.methods += ", " + method
36
+ def add_method(self, method: str):
37
+ self.methods = [*self.methods, method]
52
38
 
53
39
  def set_headers_for_input_output(self, input_output):
54
- for key in ["origin", "methods", "headers"]:
55
- if not getattr(self, key):
40
+ for key in ["expose_headers", "methods", "headers"]:
41
+ value = getattr(self, key)
42
+ if not value:
56
43
  continue
57
- input_output.set_header(f"access-control-allow-{key}".replace("_", "-"), getattr(self, key))
44
+ input_output.response_headers.add(f"access-control-allow-{key}".replace("_", "-"), ", ".join(value))
58
45
  if self.credentials:
59
- input_output.set_header("access-control-allow-credentials", "true")
60
- for key in ["max_age", "expose_headers"]:
61
- if not getattr(self, key):
62
- continue
63
- input_output.set_header(f"access-control-{key}".replace("_", "-"), str(getattr(self, key)))
64
-
65
-
66
- def cors(origin=None, methods=None, headers=None, max_age=None, credentials=None, expose_headers=None):
67
- # I didn't auto-pull into kwargs so that the allowed values are clearly defined.
68
- # however, checking and processing will be easier with a dict
69
- kwargs = {
70
- "origin": origin,
71
- "methods": methods,
72
- "headers": headers,
73
- "max_age": max_age,
74
- "credentials": credentials,
75
- "expose_headers": expose_headers,
76
- }
77
- allowed_types = {
78
- "origin": str,
79
- "max_age": int,
80
- "credentials": bool,
81
- }
82
- for key in lists:
83
- value = kwargs[key]
84
- if value is None:
85
- continue
86
- actual_type = type(value)
87
- if actual_type == list:
88
- if not all([type(item) == str for item in value]):
89
- raise ValueError(
90
- f"Invalid configuration value for CORS: {key} should be a list of strings, but another kind of value was found"
91
- )
92
- kwargs[key] = ", ".join(value)
93
- elif actual_type != str:
94
- raise ValueError(
95
- f"Invalid configuration value for CORS: {key} should be a string or list of strings but instead is '{actual_type}'"
96
- )
97
- for key, allowed_type in allowed_types.items():
98
- if kwargs[key] is None:
99
- continue
100
- actual_type = type(kwargs[key])
101
- if actual_type != allowed_type:
102
- raise ValueError(
103
- f"Invalid configuration value for CORS: {key} should be a {allowed_type} but instead is '{actual_type}'"
104
- )
105
- return BindingConfig(CORS, **kwargs)
46
+ input_output.response_headers.add("access-control-allow-credentials", "true")
47
+ if self.max_age:
48
+ input_output.response_headers.add("access-control-max-age", str(self.max_age))
49
+ if self.origin:
50
+ input_output.response_headers.add("access-control-allow-origin", str(self.origin))
@@ -1,169 +1,94 @@
1
- from .base import Base
2
- from ..binding_config import BindingConfig
1
+ import clearskies.configs
2
+ import clearskies.parameters_to_properties
3
+ from clearskies.security_header import SecurityHeader
3
4
 
4
- directives = [
5
- "default_src",
6
- "script_src",
7
- "style_src",
8
- "img_src",
9
- "connect_src",
10
- "font_src",
11
- "object_src",
12
- "media_src",
13
- "frame_src",
14
- "sandbox",
15
- "report_uri",
16
- "child_src",
17
- "form_action",
18
- "frame_ancestors",
19
- "plugin_types",
20
- "base_uri",
21
- "report_to",
22
- "worker_src",
23
- "manifest_src",
24
- "prefetch_src",
25
- "navigate_to",
26
- ]
27
5
 
28
-
29
- class CSP(Base):
6
+ class Csp(SecurityHeader):
30
7
  header_name = "content-security-policy"
31
- default_src = None
32
- script_src = None
33
- style_src = None
34
- img_src = None
35
- connect_src = None
36
- font_src = None
37
- object_src = None
38
- media_src = None
39
- frame_src = None
40
- sandbox = None
41
- report_uri = None
42
- child_src = None
43
- form_action = None
44
- frame_ancestors = None
45
- plugin_types = None
46
- base_uri = None
47
- report_to = None
48
- worker_src = None
49
- manifest_src = None
50
- prefetch_src = None
51
- navigate_to = None
8
+ default_src = clearskies.configs.String()
9
+ script_src = clearskies.configs.String()
10
+ style_src = clearskies.configs.String()
11
+ img_src = clearskies.configs.String()
12
+ connect_src = clearskies.configs.String()
13
+ font_src = clearskies.configs.String()
14
+ object_src = clearskies.configs.String()
15
+ media_src = clearskies.configs.String()
16
+ frame_src = clearskies.configs.String()
17
+ sandbox = clearskies.configs.String()
18
+ report_uri = clearskies.configs.String()
19
+ child_src = clearskies.configs.String()
20
+ form_action = clearskies.configs.String()
21
+ frame_ancestors = clearskies.configs.String()
22
+ plugin_types = clearskies.configs.String()
23
+ base_uri = clearskies.configs.String()
24
+ report_to = clearskies.configs.String()
25
+ worker_src = clearskies.configs.String()
26
+ manifest_src = clearskies.configs.String()
27
+ prefetch_src = clearskies.configs.String()
28
+ navigate_to = clearskies.configs.String()
52
29
 
53
- def __init__(self, environment):
54
- super().__init__(environment)
30
+ directives = [
31
+ "default_src",
32
+ "script_src",
33
+ "style_src",
34
+ "img_src",
35
+ "connect_src",
36
+ "font_src",
37
+ "object_src",
38
+ "media_src",
39
+ "frame_src",
40
+ "sandbox",
41
+ "report_uri",
42
+ "child_src",
43
+ "form_action",
44
+ "frame_ancestors",
45
+ "plugin_types",
46
+ "base_uri",
47
+ "report_to",
48
+ "worker_src",
49
+ "manifest_src",
50
+ "prefetch_src",
51
+ "navigate_to",
52
+ ]
55
53
 
56
- def configure(
54
+ @clearskies.parameters_to_properties.parameters_to_properties
55
+ def __init__(
57
56
  self,
58
- default_src=None,
59
- script_src=None,
60
- style_src=None,
61
- img_src=None,
62
- connect_src=None,
63
- font_src=None,
64
- object_src=None,
65
- media_src=None,
66
- frame_src=None,
67
- sandbox=None,
68
- report_uri=None,
69
- child_src=None,
70
- form_action=None,
71
- frame_ancestors=None,
72
- plugin_types=None,
73
- base_uri=None,
74
- report_to=None,
75
- worker_src=None,
76
- manifest_src=None,
77
- prefetch_src=None,
78
- navigate_to=None,
57
+ default_src: str = "",
58
+ script_src: str = "",
59
+ style_src: str = "",
60
+ img_src: str = "",
61
+ connect_src: str = "",
62
+ font_src: str = "",
63
+ object_src: str = "",
64
+ media_src: str = "",
65
+ frame_src: str = "",
66
+ sandbox: str = "",
67
+ report_uri: str = "",
68
+ child_src: str = "",
69
+ form_action: str = "",
70
+ frame_ancestors: str = "",
71
+ plugin_types: str = "",
72
+ base_uri: str = "",
73
+ report_to: str = "",
74
+ worker_src: str = "",
75
+ manifest_src: str = "",
76
+ prefetch_src: str = "",
77
+ navigate_to: str = "",
79
78
  ):
80
- self.default_src = default_src
81
- self.script_src = script_src
82
- self.style_src = style_src
83
- self.img_src = img_src
84
- self.connect_src = connect_src
85
- self.font_src = font_src
86
- self.object_src = object_src
87
- self.media_src = media_src
88
- self.frame_src = frame_src
89
- self.sandbox = sandbox
90
- self.report_uri = report_uri
91
- self.child_src = child_src
92
- self.form_action = form_action
93
- self.frame_ancestors = frame_ancestors
94
- self.plugin_types = plugin_types
95
- self.base_uri = base_uri
96
- self.report_to = report_to
97
- self.worker_src = worker_src
98
- self.manifest_src = manifest_src
99
- self.prefetch_src = prefetch_src
100
- self.navigate_to = navigate_to
79
+ self.finalize_and_validate_configuration()
101
80
 
102
81
  def set_headers_for_input_output(self, input_output):
103
82
  parts = []
104
- for variable_name in directives:
83
+ for variable_name in self.directives:
105
84
  value = getattr(self, variable_name)
106
85
  if not value:
107
86
  continue
87
+ if value.lower().strip() == "self":
88
+ value = "'self'"
108
89
  header_key_name = variable_name.replace("_", "-")
109
90
  parts.append(f"{header_key_name} {value}")
110
91
  if not parts:
111
92
  return
112
93
  header_value = "; ".join(parts)
113
- input_output.set_header(self.header_name, header_value)
114
-
115
-
116
- def csp(
117
- default_src=None,
118
- script_src=None,
119
- style_src=None,
120
- img_src=None,
121
- connect_src=None,
122
- font_src=None,
123
- object_src=None,
124
- media_src=None,
125
- frame_src=None,
126
- sandbox=None,
127
- report_uri=None,
128
- child_src=None,
129
- form_action=None,
130
- frame_ancestors=None,
131
- plugin_types=None,
132
- base_uri=None,
133
- report_to=None,
134
- worker_src=None,
135
- manifest_src=None,
136
- prefetch_src=None,
137
- navigate_to=None,
138
- ):
139
- for variable_name in directives:
140
- value = locals()[variable_name]
141
- if value is not None and type(value) != str:
142
- actual_type = type(value)
143
- raise ValueError(
144
- f"Invalid configuration value for CSP: {variable_name} should be a string but instead is '{actual_type}'"
145
- )
146
- return BindingConfig(
147
- CSP,
148
- default_src=default_src,
149
- script_src=script_src,
150
- style_src=style_src,
151
- img_src=img_src,
152
- connect_src=connect_src,
153
- font_src=font_src,
154
- object_src=object_src,
155
- media_src=media_src,
156
- frame_src=frame_src,
157
- sandbox=sandbox,
158
- report_uri=report_uri,
159
- child_src=child_src,
160
- form_action=form_action,
161
- frame_ancestors=frame_ancestors,
162
- plugin_types=plugin_types,
163
- base_uri=base_uri,
164
- report_to=report_to,
165
- worker_src=worker_src,
166
- manifest_src=manifest_src,
167
- prefetch_src=prefetch_src,
168
- navigate_to=navigate_to,
169
- )
94
+ input_output.response_headers.add(self.header_name, header_value)
@@ -1,24 +1,22 @@
1
- from .base import Base
2
- from ..binding_config import BindingConfig
1
+ import clearskies.configs
2
+ import clearskies.parameters_to_properties
3
+ from clearskies.security_header import SecurityHeader
3
4
 
4
5
 
5
- class HSTS(Base):
6
- max_age = None
7
- include_sub_domains = None
6
+ class Hsts(SecurityHeader):
7
+ max_age = clearskies.configs.Integer(default=31536000)
8
+ include_sub_domains = clearskies.configs.Boolean()
8
9
 
9
- def __init__(self, environment):
10
- super().__init__(environment)
11
-
12
- def configure(self, max_age=31536000, include_sub_domains=False):
13
- self.max_age = max_age
14
- self.include_sub_domains = include_sub_domains
10
+ @clearskies.parameters_to_properties.parameters_to_properties
11
+ def __init__(
12
+ self,
13
+ max_age: int = 31536000,
14
+ include_sub_domains: bool = False,
15
+ ):
16
+ self.finalize_and_validate_configuration()
15
17
 
16
18
  def set_headers_for_input_output(self, input_output):
17
19
  value = f"max-age={self.max_age} ;"
18
20
  if self.include_sub_domains:
19
21
  value += " includeSubDomains"
20
- input_output.set_header("strict-transport-security", value)
21
-
22
-
23
- def hsts(max_age=31536000, include_sub_domains=False):
24
- return BindingConfig(HSTS, max_age=max_age, include_sub_domains=include_sub_domains)
22
+ input_output.response_headers.add("strict-transport-security", value)
@@ -0,0 +1,8 @@
1
+ import unittest
2
+
3
+
4
+ class TestBase(unittest.TestCase):
5
+ def tearDown(self):
6
+ import clearskies.backends.memory_backend
7
+
8
+ clearskies.backends.memory_backend.MemoryBackend.clear_table_cache()
clearskies/typing.py ADDED
@@ -0,0 +1,11 @@
1
+ from typing import Any, Callable
2
+
3
+ from clearskies.action import Action
4
+ from clearskies.query.condition import Condition
5
+ from clearskies.validator import Validator
6
+
7
+ action = Callable[..., dict[str, Any]] | Action
8
+ condition = str | Callable | Condition
9
+ join = str | Callable[..., str]
10
+ validator = Callable[..., str] | Validator
11
+ response = str | bytes | dict[str, Any] | list[Any]
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import TYPE_CHECKING, Any
5
+
6
+ from clearskies import configurable
7
+
8
+ if TYPE_CHECKING:
9
+ import clearskies.column
10
+ import clearskies.model
11
+
12
+
13
+ class Validator(ABC, configurable.Configurable):
14
+ is_unique = False
15
+ is_required = False
16
+
17
+ def __call__(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
18
+ return self.check(model, column_name, data)
19
+
20
+ @abstractmethod
21
+ def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
22
+ pass
23
+
24
+ def additional_write_columns(self, is_create=False) -> dict[str, clearskies.column.Column]:
25
+ return {}