clear-skies 1.22.10__py3-none-any.whl → 2.0.23__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.
Files changed (368) hide show
  1. clear_skies-2.0.23.dist-info/METADATA +76 -0
  2. clear_skies-2.0.23.dist-info/RECORD +265 -0
  3. {clear_skies-1.22.10.dist-info → clear_skies-2.0.23.dist-info}/WHEEL +1 -1
  4. clearskies/__init__.py +37 -21
  5. clearskies/action.py +7 -0
  6. clearskies/authentication/__init__.py +8 -39
  7. clearskies/authentication/authentication.py +44 -0
  8. clearskies/authentication/authorization.py +14 -8
  9. clearskies/authentication/authorization_pass_through.py +14 -10
  10. clearskies/authentication/jwks.py +135 -58
  11. clearskies/authentication/public.py +3 -26
  12. clearskies/authentication/secret_bearer.py +515 -44
  13. clearskies/autodoc/formats/oai3_json/__init__.py +2 -2
  14. clearskies/autodoc/formats/oai3_json/oai3_json.py +11 -9
  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 +10 -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 +16 -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 +1118 -280
  42. clearskies/backends/backend.py +54 -85
  43. clearskies/backends/cursor_backend.py +246 -191
  44. clearskies/backends/memory_backend.py +514 -208
  45. clearskies/backends/secrets_backend.py +68 -31
  46. clearskies/column.py +1221 -0
  47. clearskies/columns/__init__.py +71 -0
  48. clearskies/columns/audit.py +306 -0
  49. clearskies/columns/belongs_to_id.py +478 -0
  50. clearskies/columns/belongs_to_model.py +129 -0
  51. clearskies/columns/belongs_to_self.py +109 -0
  52. clearskies/columns/boolean.py +110 -0
  53. clearskies/columns/category_tree.py +273 -0
  54. clearskies/columns/category_tree_ancestors.py +51 -0
  55. clearskies/columns/category_tree_children.py +126 -0
  56. clearskies/columns/category_tree_descendants.py +48 -0
  57. clearskies/columns/created.py +92 -0
  58. clearskies/columns/created_by_authorization_data.py +114 -0
  59. clearskies/columns/created_by_header.py +103 -0
  60. clearskies/columns/created_by_ip.py +90 -0
  61. clearskies/columns/created_by_routing_data.py +102 -0
  62. clearskies/columns/created_by_user_agent.py +89 -0
  63. clearskies/columns/date.py +232 -0
  64. clearskies/columns/datetime.py +284 -0
  65. clearskies/columns/email.py +78 -0
  66. clearskies/columns/float.py +149 -0
  67. clearskies/columns/has_many.py +529 -0
  68. clearskies/columns/has_many_self.py +62 -0
  69. clearskies/columns/has_one.py +21 -0
  70. clearskies/columns/integer.py +158 -0
  71. clearskies/columns/json.py +126 -0
  72. clearskies/columns/many_to_many_ids.py +335 -0
  73. clearskies/columns/many_to_many_ids_with_data.py +274 -0
  74. clearskies/columns/many_to_many_models.py +156 -0
  75. clearskies/columns/many_to_many_pivots.py +132 -0
  76. clearskies/columns/phone.py +162 -0
  77. clearskies/columns/select.py +95 -0
  78. clearskies/columns/string.py +102 -0
  79. clearskies/columns/timestamp.py +164 -0
  80. clearskies/columns/updated.py +107 -0
  81. clearskies/columns/uuid.py +83 -0
  82. clearskies/configs/README.md +105 -0
  83. clearskies/configs/__init__.py +170 -0
  84. clearskies/configs/actions.py +43 -0
  85. clearskies/configs/any.py +15 -0
  86. clearskies/configs/any_dict.py +24 -0
  87. clearskies/configs/any_dict_or_callable.py +25 -0
  88. clearskies/configs/authentication.py +23 -0
  89. clearskies/configs/authorization.py +23 -0
  90. clearskies/configs/boolean.py +18 -0
  91. clearskies/configs/boolean_or_callable.py +20 -0
  92. clearskies/configs/callable_config.py +20 -0
  93. clearskies/configs/columns.py +34 -0
  94. clearskies/configs/conditions.py +30 -0
  95. clearskies/configs/config.py +26 -0
  96. clearskies/configs/datetime.py +20 -0
  97. clearskies/configs/datetime_or_callable.py +21 -0
  98. clearskies/configs/email.py +10 -0
  99. clearskies/configs/email_list.py +17 -0
  100. clearskies/configs/email_list_or_callable.py +17 -0
  101. clearskies/configs/email_or_email_list_or_callable.py +59 -0
  102. clearskies/configs/endpoint.py +23 -0
  103. clearskies/configs/endpoint_list.py +29 -0
  104. clearskies/configs/float.py +18 -0
  105. clearskies/configs/float_or_callable.py +20 -0
  106. clearskies/configs/headers.py +28 -0
  107. clearskies/configs/integer.py +18 -0
  108. clearskies/configs/integer_or_callable.py +20 -0
  109. clearskies/configs/joins.py +30 -0
  110. clearskies/configs/list_any_dict.py +32 -0
  111. clearskies/configs/list_any_dict_or_callable.py +33 -0
  112. clearskies/configs/model_class.py +35 -0
  113. clearskies/configs/model_column.py +67 -0
  114. clearskies/configs/model_columns.py +58 -0
  115. clearskies/configs/model_destination_name.py +26 -0
  116. clearskies/configs/model_to_id_column.py +45 -0
  117. clearskies/configs/readable_model_column.py +11 -0
  118. clearskies/configs/readable_model_columns.py +11 -0
  119. clearskies/configs/schema.py +23 -0
  120. clearskies/configs/searchable_model_columns.py +11 -0
  121. clearskies/configs/security_headers.py +39 -0
  122. clearskies/configs/select.py +28 -0
  123. clearskies/configs/select_list.py +49 -0
  124. clearskies/configs/string.py +31 -0
  125. clearskies/configs/string_dict.py +34 -0
  126. clearskies/configs/string_list.py +47 -0
  127. clearskies/configs/string_list_or_callable.py +48 -0
  128. clearskies/configs/string_or_callable.py +18 -0
  129. clearskies/configs/timedelta.py +20 -0
  130. clearskies/configs/timezone.py +20 -0
  131. clearskies/configs/url.py +25 -0
  132. clearskies/configs/validators.py +45 -0
  133. clearskies/configs/writeable_model_column.py +11 -0
  134. clearskies/configs/writeable_model_columns.py +11 -0
  135. clearskies/configurable.py +78 -0
  136. clearskies/contexts/__init__.py +8 -8
  137. clearskies/contexts/cli.py +129 -43
  138. clearskies/contexts/context.py +93 -56
  139. clearskies/contexts/wsgi.py +79 -33
  140. clearskies/contexts/wsgi_ref.py +87 -0
  141. clearskies/cursors/__init__.py +7 -0
  142. clearskies/cursors/cursor.py +166 -0
  143. clearskies/cursors/from_environment/__init__.py +5 -0
  144. clearskies/cursors/from_environment/mysql.py +51 -0
  145. clearskies/cursors/from_environment/postgresql.py +49 -0
  146. clearskies/cursors/from_environment/sqlite.py +35 -0
  147. clearskies/cursors/mysql.py +61 -0
  148. clearskies/cursors/postgresql.py +61 -0
  149. clearskies/cursors/sqlite.py +62 -0
  150. clearskies/decorators.py +33 -0
  151. clearskies/decorators.pyi +10 -0
  152. clearskies/di/__init__.py +11 -7
  153. clearskies/di/additional_config.py +115 -4
  154. clearskies/di/additional_config_auto_import.py +12 -0
  155. clearskies/di/di.py +714 -125
  156. clearskies/di/inject/__init__.py +23 -0
  157. clearskies/di/inject/akeyless_sdk.py +16 -0
  158. clearskies/di/inject/by_class.py +24 -0
  159. clearskies/di/inject/by_name.py +22 -0
  160. clearskies/di/inject/di.py +16 -0
  161. clearskies/di/inject/environment.py +15 -0
  162. clearskies/di/inject/input_output.py +19 -0
  163. clearskies/di/inject/now.py +16 -0
  164. clearskies/di/inject/requests.py +16 -0
  165. clearskies/di/inject/secrets.py +15 -0
  166. clearskies/di/inject/utcnow.py +16 -0
  167. clearskies/di/inject/uuid.py +16 -0
  168. clearskies/di/injectable.py +32 -0
  169. clearskies/di/injectable_properties.py +131 -0
  170. clearskies/end.py +219 -0
  171. clearskies/endpoint.py +1303 -0
  172. clearskies/endpoint_group.py +333 -0
  173. clearskies/endpoints/__init__.py +25 -0
  174. clearskies/endpoints/advanced_search.py +519 -0
  175. clearskies/endpoints/callable.py +382 -0
  176. clearskies/endpoints/create.py +201 -0
  177. clearskies/endpoints/delete.py +133 -0
  178. clearskies/endpoints/get.py +267 -0
  179. clearskies/endpoints/health_check.py +181 -0
  180. clearskies/endpoints/list.py +567 -0
  181. clearskies/endpoints/restful_api.py +417 -0
  182. clearskies/endpoints/schema.py +185 -0
  183. clearskies/endpoints/simple_search.py +279 -0
  184. clearskies/endpoints/update.py +188 -0
  185. clearskies/environment.py +7 -3
  186. clearskies/exceptions/__init__.py +19 -0
  187. clearskies/{handlers/exceptions/input_error.py → exceptions/input_errors.py} +1 -1
  188. clearskies/exceptions/missing_dependency.py +2 -0
  189. clearskies/exceptions/moved_permanently.py +3 -0
  190. clearskies/exceptions/moved_temporarily.py +3 -0
  191. clearskies/functional/__init__.py +2 -2
  192. clearskies/functional/json.py +47 -0
  193. clearskies/functional/routing.py +92 -0
  194. clearskies/functional/string.py +19 -11
  195. clearskies/functional/validations.py +61 -9
  196. clearskies/input_outputs/__init__.py +9 -7
  197. clearskies/input_outputs/cli.py +135 -160
  198. clearskies/input_outputs/exceptions/__init__.py +6 -1
  199. clearskies/input_outputs/headers.py +54 -0
  200. clearskies/input_outputs/input_output.py +77 -123
  201. clearskies/input_outputs/programmatic.py +62 -0
  202. clearskies/input_outputs/wsgi.py +36 -48
  203. clearskies/model.py +1874 -193
  204. clearskies/query/__init__.py +12 -0
  205. clearskies/query/condition.py +228 -0
  206. clearskies/query/join.py +136 -0
  207. clearskies/query/query.py +193 -0
  208. clearskies/query/sort.py +27 -0
  209. clearskies/schema.py +82 -0
  210. clearskies/secrets/__init__.py +4 -31
  211. clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py +15 -4
  212. clearskies/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +11 -5
  213. clearskies/secrets/akeyless.py +421 -155
  214. clearskies/secrets/exceptions/__init__.py +7 -1
  215. clearskies/secrets/exceptions/not_found_error.py +2 -0
  216. clearskies/secrets/exceptions/permissions_error.py +2 -0
  217. clearskies/secrets/secrets.py +12 -11
  218. clearskies/security_header.py +17 -0
  219. clearskies/security_headers/__init__.py +8 -8
  220. clearskies/security_headers/cache_control.py +47 -109
  221. clearskies/security_headers/cors.py +38 -92
  222. clearskies/security_headers/csp.py +76 -150
  223. clearskies/security_headers/hsts.py +14 -15
  224. clearskies/typing.py +11 -0
  225. clearskies/validator.py +36 -0
  226. clearskies/validators/__init__.py +33 -0
  227. clearskies/validators/after_column.py +61 -0
  228. clearskies/validators/before_column.py +15 -0
  229. clearskies/validators/in_the_future.py +29 -0
  230. clearskies/validators/in_the_future_at_least.py +13 -0
  231. clearskies/validators/in_the_future_at_most.py +12 -0
  232. clearskies/validators/in_the_past.py +29 -0
  233. clearskies/validators/in_the_past_at_least.py +12 -0
  234. clearskies/validators/in_the_past_at_most.py +12 -0
  235. clearskies/validators/maximum_length.py +25 -0
  236. clearskies/validators/maximum_value.py +28 -0
  237. clearskies/validators/minimum_length.py +25 -0
  238. clearskies/validators/minimum_value.py +28 -0
  239. clearskies/{input_requirements → validators}/required.py +18 -9
  240. clearskies/validators/timedelta.py +58 -0
  241. clearskies/validators/unique.py +28 -0
  242. clear_skies-1.22.10.dist-info/METADATA +0 -47
  243. clear_skies-1.22.10.dist-info/RECORD +0 -213
  244. clearskies/application.py +0 -29
  245. clearskies/authentication/auth0_jwks.py +0 -118
  246. clearskies/authentication/auth_exception.py +0 -2
  247. clearskies/authentication/jwks_jwcrypto.py +0 -51
  248. clearskies/backends/api_get_only_backend.py +0 -48
  249. clearskies/backends/example_backend.py +0 -43
  250. clearskies/backends/file_backend.py +0 -48
  251. clearskies/backends/json_backend.py +0 -7
  252. clearskies/backends/restful_api_advanced_search_backend.py +0 -103
  253. clearskies/binding_config.py +0 -16
  254. clearskies/column_types/__init__.py +0 -203
  255. clearskies/column_types/audit.py +0 -249
  256. clearskies/column_types/belongs_to.py +0 -271
  257. clearskies/column_types/boolean.py +0 -60
  258. clearskies/column_types/category_tree.py +0 -304
  259. clearskies/column_types/column.py +0 -373
  260. clearskies/column_types/created.py +0 -26
  261. clearskies/column_types/created_by_authorization_data.py +0 -26
  262. clearskies/column_types/created_by_header.py +0 -24
  263. clearskies/column_types/created_by_ip.py +0 -17
  264. clearskies/column_types/created_by_routing_data.py +0 -25
  265. clearskies/column_types/created_by_user_agent.py +0 -17
  266. clearskies/column_types/created_micro.py +0 -26
  267. clearskies/column_types/datetime.py +0 -109
  268. clearskies/column_types/datetime_micro.py +0 -13
  269. clearskies/column_types/email.py +0 -18
  270. clearskies/column_types/float.py +0 -43
  271. clearskies/column_types/has_many.py +0 -179
  272. clearskies/column_types/has_one.py +0 -58
  273. clearskies/column_types/integer.py +0 -41
  274. clearskies/column_types/json.py +0 -25
  275. clearskies/column_types/many_to_many.py +0 -278
  276. clearskies/column_types/many_to_many_with_data.py +0 -162
  277. clearskies/column_types/phone.py +0 -48
  278. clearskies/column_types/select.py +0 -11
  279. clearskies/column_types/string.py +0 -24
  280. clearskies/column_types/timestamp.py +0 -73
  281. clearskies/column_types/updated.py +0 -26
  282. clearskies/column_types/updated_micro.py +0 -26
  283. clearskies/column_types/uuid.py +0 -25
  284. clearskies/columns.py +0 -123
  285. clearskies/condition_parser.py +0 -172
  286. clearskies/contexts/build_context.py +0 -54
  287. clearskies/contexts/convert_to_application.py +0 -190
  288. clearskies/contexts/extract_handler.py +0 -37
  289. clearskies/contexts/test.py +0 -94
  290. clearskies/decorators/__init__.py +0 -39
  291. clearskies/decorators/auth0_jwks.py +0 -22
  292. clearskies/decorators/authorization.py +0 -10
  293. clearskies/decorators/binding_classes.py +0 -9
  294. clearskies/decorators/binding_modules.py +0 -9
  295. clearskies/decorators/bindings.py +0 -9
  296. clearskies/decorators/create.py +0 -10
  297. clearskies/decorators/delete.py +0 -10
  298. clearskies/decorators/docs.py +0 -14
  299. clearskies/decorators/get.py +0 -10
  300. clearskies/decorators/jwks.py +0 -26
  301. clearskies/decorators/merge.py +0 -124
  302. clearskies/decorators/patch.py +0 -10
  303. clearskies/decorators/post.py +0 -10
  304. clearskies/decorators/public.py +0 -11
  305. clearskies/decorators/response_headers.py +0 -10
  306. clearskies/decorators/return_raw_response.py +0 -9
  307. clearskies/decorators/schema.py +0 -10
  308. clearskies/decorators/secret_bearer.py +0 -24
  309. clearskies/decorators/security_headers.py +0 -10
  310. clearskies/di/standard_dependencies.py +0 -151
  311. clearskies/di/test_module/__init__.py +0 -6
  312. clearskies/di/test_module/another_module/__init__.py +0 -2
  313. clearskies/di/test_module/module_class.py +0 -5
  314. clearskies/handlers/__init__.py +0 -41
  315. clearskies/handlers/advanced_search.py +0 -271
  316. clearskies/handlers/base.py +0 -479
  317. clearskies/handlers/callable.py +0 -191
  318. clearskies/handlers/create.py +0 -35
  319. clearskies/handlers/crud_by_method.py +0 -18
  320. clearskies/handlers/database_connector.py +0 -32
  321. clearskies/handlers/delete.py +0 -61
  322. clearskies/handlers/exceptions/__init__.py +0 -5
  323. clearskies/handlers/exceptions/not_found.py +0 -3
  324. clearskies/handlers/get.py +0 -156
  325. clearskies/handlers/health_check.py +0 -59
  326. clearskies/handlers/input_processing.py +0 -79
  327. clearskies/handlers/list.py +0 -530
  328. clearskies/handlers/mygrations.py +0 -82
  329. clearskies/handlers/request_method_routing.py +0 -47
  330. clearskies/handlers/restful_api.py +0 -218
  331. clearskies/handlers/routing.py +0 -62
  332. clearskies/handlers/schema_helper.py +0 -128
  333. clearskies/handlers/simple_routing.py +0 -206
  334. clearskies/handlers/simple_routing_route.py +0 -192
  335. clearskies/handlers/simple_search.py +0 -136
  336. clearskies/handlers/update.py +0 -96
  337. clearskies/handlers/write.py +0 -193
  338. clearskies/input_requirements/__init__.py +0 -78
  339. clearskies/input_requirements/after.py +0 -36
  340. clearskies/input_requirements/before.py +0 -36
  341. clearskies/input_requirements/in_the_future_at_least.py +0 -19
  342. clearskies/input_requirements/in_the_future_at_most.py +0 -19
  343. clearskies/input_requirements/in_the_past_at_least.py +0 -19
  344. clearskies/input_requirements/in_the_past_at_most.py +0 -19
  345. clearskies/input_requirements/maximum_length.py +0 -19
  346. clearskies/input_requirements/maximum_value.py +0 -19
  347. clearskies/input_requirements/minimum_length.py +0 -22
  348. clearskies/input_requirements/minimum_value.py +0 -19
  349. clearskies/input_requirements/requirement.py +0 -25
  350. clearskies/input_requirements/time_delta.py +0 -38
  351. clearskies/input_requirements/unique.py +0 -18
  352. clearskies/mocks/__init__.py +0 -7
  353. clearskies/mocks/input_output.py +0 -124
  354. clearskies/mocks/models.py +0 -142
  355. clearskies/models.py +0 -350
  356. clearskies/security_headers/base.py +0 -12
  357. clearskies/tests/simple_api/models/__init__.py +0 -2
  358. clearskies/tests/simple_api/models/status.py +0 -23
  359. clearskies/tests/simple_api/models/user.py +0 -21
  360. clearskies/tests/simple_api/users_api.py +0 -64
  361. {clear_skies-1.22.10.dist-info → clear_skies-2.0.23.dist-info/licenses}/LICENSE +0 -0
  362. /clearskies/{contexts/bash.py → autodoc/py.typed} +0 -0
  363. /clearskies/{handlers/exceptions → exceptions}/authentication.py +0 -0
  364. /clearskies/{handlers/exceptions → exceptions}/authorization.py +0 -0
  365. /clearskies/{handlers/exceptions → exceptions}/client_error.py +0 -0
  366. /clearskies/{secrets/exceptions → exceptions}/not_found.py +0 -0
  367. /clearskies/{tests/__init__.py → input_outputs/py.typed} +0 -0
  368. /clearskies/{tests/simple_api/__init__.py → py.typed} +0 -0
clearskies/models.py DELETED
@@ -1,350 +0,0 @@
1
- from abc import ABC, abstractmethod
2
- from .condition_parser import ConditionParser
3
- from typing import Any, Callable, Dict, List, Tuple, Iterator
4
-
5
- try:
6
- from typing_extensions import Self
7
- except ModuleNotFoundError:
8
- from typing import Self
9
-
10
-
11
- class Models(ABC, ConditionParser):
12
- # The database connection
13
- _backend = None
14
- _columns = None
15
- _model_columns = None
16
- _next_page_data = None
17
-
18
- query_wheres = None
19
- query_sorts = None
20
- query_group_by_column = None
21
- query_limit = None
22
- query_pagination = None
23
- query_selects = None
24
- query_select_all = None
25
- must_rexecute = True
26
- must_recount = True
27
- count = None
28
- _table_name = None
29
- _id_column_name = None
30
- _query_configuration = None
31
-
32
- def __init__(self, backend, columns):
33
- self._model_columns = None
34
- self._backend = backend
35
- self._columns = columns
36
- self.must_rexecute = True
37
- self._next_page_data = None
38
- self.must_recount = True
39
-
40
- self.query_wheres = []
41
- self.query_sorts = []
42
- self.query_group_by_column = None
43
- self.query_joins = []
44
- self.query_limit = None
45
- self.query_pagination = {}
46
- self.query_selects = []
47
- self.query_select_all = True
48
-
49
- @abstractmethod
50
- def model_class(self: Self) -> type[Self]:
51
- """Return the model class that this models object will find/return instances of"""
52
- pass
53
-
54
- def clone(self: Self) -> Self:
55
- clone = self.blank()
56
- clone.query_configuration = self.query_configuration
57
- return clone
58
-
59
- def blank(self: Self) -> Self:
60
- return self._build_model()
61
-
62
- def get_table_name(self: Self) -> str:
63
- if self._table_name is None:
64
- self._table_name = self.model_class().table_name()
65
- return self._table_name
66
-
67
- def get_id_column_name(self: Self) -> str:
68
- if self._id_column_name is None:
69
- self._id_column_name = self.empty_model().id_column_name
70
- return self._id_column_name
71
-
72
- @property
73
- def query_configuration(self: Self) -> Dict[str, Any]:
74
- return {
75
- "wheres": [*self.query_wheres],
76
- "sorts": [*self.query_sorts],
77
- "group_by_column": self.query_group_by_column,
78
- "joins": [*self.query_joins],
79
- "limit": self.query_limit,
80
- "pagination": self.query_pagination,
81
- "selects": self.query_selects,
82
- "select_all": self.query_select_all,
83
- "table_name": self.get_table_name(),
84
- "model_columns": self.model_columns,
85
- }
86
-
87
- @query_configuration.setter
88
- def query_configuration(self: Self, configuration: Dict[str, Any]):
89
- self.query_wheres = configuration["wheres"]
90
- self.query_sorts = configuration["sorts"]
91
- self.query_group_by_column = configuration["group_by_column"]
92
- self.query_joins = configuration["joins"]
93
- self.query_limit = configuration["limit"]
94
- self.query_pagination = configuration["pagination"]
95
- self.query_selects = configuration["selects"]
96
- self.query_select_all = configuration["select_all"]
97
- self._model_columns = configuration["model_columns"]
98
-
99
- @property
100
- def model_columns(self: Self):
101
- if self._model_columns is None:
102
- self._model_columns = self.empty_model().columns()
103
- return self._model_columns
104
-
105
- def select(self: Self, selects) -> Self:
106
- return self.clone().select_in_place(selects)
107
-
108
- def select_in_place(self: Self, selects) -> Self:
109
- self.query_selects.append(selects)
110
- self.must_rexecute = True
111
- self._next_page_data = None
112
- return self
113
-
114
- def select_all(self: Self, select_all=True) -> Self:
115
- return self.clone().select_all_in_place(select_all=select_all)
116
-
117
- def select_all_in_place(self: Self, select_all=True) -> Self:
118
- self.query_select_all = select_all
119
- self.must_rexecute = True
120
- self._next_page_data = None
121
- return self
122
-
123
- def where(self: Self, where: str) -> Self:
124
- """Adds the given condition to the query and returns a new Models object"""
125
- return self.clone().where_in_place(where)
126
-
127
- def where_in_place(self: Self, where: str) -> Self:
128
- """Adds the given condition to the query for the current Models object"""
129
- condition = self.parse_condition(where)
130
- self._validate_column(condition["column"], "filter", table=condition["table"])
131
- self.query_wheres.append(self.parse_condition(where))
132
- self.must_rexecute = True
133
- self._next_page_data = None
134
- self.must_recount = True
135
- return self
136
-
137
- def join(self: Self, join: str) -> Self:
138
- return self.clone().join_in_place(join)
139
-
140
- def join_in_place(self: Self, join: str) -> Self:
141
- self.query_joins.append(self.parse_join(join))
142
- self.must_rexecute = True
143
- self._next_page_data = None
144
- self.must_recount = True
145
- return self
146
-
147
- def is_joined(self: Self, table_name, alias=None):
148
- for join in self.query_joins:
149
- if join["table"] != table_name:
150
- continue
151
-
152
- if alias and join["alias"] != alias:
153
- continue
154
-
155
- return join["alias"] if join["alias"] else join["table"]
156
- return False
157
-
158
- def group_by(self: Self, group_column: str) -> Self:
159
- return self.clone().group_by_in_place(group_column)
160
-
161
- def group_by_in_place(self: Self, group_column: str) -> Self:
162
- self._validate_column(group_column, "group")
163
- self.query_group_by_column = group_column
164
- self.must_rexecute = True
165
- self._next_page_data = None
166
- self.must_recount = True
167
- return self
168
-
169
- def sort_by(
170
- self: Self,
171
- primary_column,
172
- primary_direction,
173
- primary_table=None,
174
- secondary_column=None,
175
- secondary_direction=None,
176
- secondary_table=None,
177
- ) -> Self:
178
- return self.clone().sort_by_in_place(
179
- primary_column,
180
- primary_direction,
181
- primary_table=primary_table,
182
- secondary_column=secondary_column,
183
- secondary_direction=secondary_direction,
184
- secondary_table=secondary_table,
185
- )
186
-
187
- def sort_by_in_place(
188
- self: Self,
189
- primary_column,
190
- primary_direction,
191
- primary_table=None,
192
- secondary_column=None,
193
- secondary_direction=None,
194
- secondary_table=None,
195
- ) -> Self:
196
- sorts = [
197
- {"table": primary_table, "column": primary_column, "direction": primary_direction},
198
- {"table": secondary_table, "column": secondary_column, "direction": secondary_direction},
199
- ]
200
- sorts = filter(lambda sort: sort["column"] is not None and sort["direction"] is not None, sorts)
201
- self.query_sorts = list(map(lambda sort: self._normalize_and_validate_sort(sort), sorts))
202
- if len(self.query_sorts) == 0:
203
- raise ValueError("Missing primary column or direction in call to sort_by")
204
- self.must_rexecute = True
205
- self._next_page_data = None
206
- return self
207
-
208
- def _normalize_and_validate_sort(self: Self, sort):
209
- if "column" not in sort or not sort["column"]:
210
- raise ValueError("Missing 'column' for sort")
211
- if "direction" not in sort or not sort["direction"]:
212
- raise ValueError("Missing 'direction' for sort: should be ASC or DESC")
213
- direction = sort["direction"].upper().strip()
214
- if direction != "ASC" and direction != "DESC":
215
- raise ValueError(f"Invalid sort direction: should be ASC or DESC, not '{direction}'")
216
- self._validate_column(sort["column"], "sort", table=sort.get("table"))
217
-
218
- # down the line we may ask the model class what columns we can sort on, but we're good for now
219
- return {"column": sort["column"], "direction": sort["direction"], "table": sort.get("table")}
220
-
221
- def _validate_column(self: Self, column_name, action, table=None):
222
- """
223
- Down the line we may use the model configuration to check what columns are valid sort/group/search targets
224
- """
225
- # for now, only validate columns that belong to *our* table.
226
- # in some cases we are explicitly told the column name
227
- if table is not None:
228
- # note that table may be '', in which case it is implicitly "our" table
229
- if table != "" and table != self.get_table_name():
230
- return
231
-
232
- # but in some cases we should check and see if it is included with the column name
233
- column_name = column_name.replace("`", "")
234
- if "." in column_name:
235
- parts = column_name.split(".")
236
- if parts[0] != self.get_table_name():
237
- return
238
- column_name = column_name.split(".")[1]
239
-
240
- model_columns = self.model_columns
241
- if column_name not in model_columns:
242
- model_class = self.model_class()
243
- raise KeyError(
244
- f"Cannot {action} by column '{column_name}' for model class {model_class.__name__} because this "
245
- + "column does not exist for the model. You can suppress this error by adding a matching column "
246
- + "to your model definition"
247
- )
248
-
249
- def limit(self: Self, limit) -> Self:
250
- return self.clone().limit_in_place(limit)
251
-
252
- def limit_in_place(self: Self, limit) -> Self:
253
- self.query_limit = limit
254
- self.must_rexecute = True
255
- self._next_page_data = None
256
- return self
257
-
258
- def pagination(self: Self, **kwargs) -> Self:
259
- return self.clone().pagination_in_place(**kwargs)
260
-
261
- def pagination_in_place(self: Self, **kwargs) -> Self:
262
- error = self._backend.validate_pagination_kwargs(kwargs, str)
263
- if error:
264
- raise ValueError(
265
- f"Invalid pagination data for model {self.__class__.__name__} with backend "
266
- + f"{self._backend.__class__.__name__}. {error}"
267
- )
268
- self.query_pagination = kwargs
269
- self.must_rexecute = True
270
- self._next_page_data = None
271
- return self
272
-
273
- def find(self: Self, where: str) -> Self:
274
- """Returns the first model where condition"""
275
- return self.clone().where(where).first()
276
-
277
- def __len__(self: Self):
278
- if self.must_recount:
279
- self.count = self._backend.count(self.query_configuration, self.empty_model())
280
- self.must_recount = False
281
- return self.count
282
-
283
- def __iter__(self: Self) -> Iterator[Self]:
284
- self._next_page_data = {}
285
- raw_rows = self._backend.records(
286
- self.query_configuration,
287
- self.empty_model(),
288
- next_page_data=self._next_page_data,
289
- )
290
- models = iter([self.model(row) for row in raw_rows])
291
- return models
292
-
293
- def paginate_all(self: Self) -> List[Self]:
294
- next_models = self.clone()
295
- results = list(next_models.__iter__())
296
- next_page_data = next_models.next_page_data()
297
- while next_page_data:
298
- next_models = next_models.clone().pagination(**next_page_data)
299
- results.extend(next_models.__iter__())
300
- next_page_data = next_models.next_page_data()
301
- return results
302
-
303
- def model(self: Self, data) -> Self:
304
- model = self._build_model()
305
- model.data = data
306
- return model
307
-
308
- def _build_model(self: Self) -> Self:
309
- model_class = self.model_class()
310
- return model_class(self._backend, self._columns)
311
-
312
- def empty_model(self: Self) -> Self:
313
- return self.model({})
314
-
315
- def create(self: Self, data: Dict[str, Any]) -> Self:
316
- empty = self.empty_model()
317
- empty.save(data)
318
- return empty
319
-
320
- def first(self: Self) -> Self:
321
- iter = self.__iter__()
322
- try:
323
- return iter.__next__()
324
- except StopIteration:
325
- return self.empty_model()
326
-
327
- def columns(self: Self, overrides=None):
328
- model = self.model({})
329
- return model.columns(overrides=None)
330
-
331
- def raw_columns_configuration(self: Self):
332
- return self.model({}).all_columns()
333
-
334
- def allowed_pagination_keys(self: Self) -> List[str]:
335
- return self._backend.allowed_pagination_keys()
336
-
337
- def validate_pagination_kwargs(self, kwargs: Dict[str, Any], case_mapping: Callable) -> str:
338
- return self._backend.validate_pagination_kwargs(kwargs, case_mapping)
339
-
340
- def next_page_data(self: Self):
341
- return self._next_page_data
342
-
343
- def documentation_pagination_next_page_response(self: Self, case_mapping: Callable) -> List[Any]:
344
- return self._backend.documentation_pagination_next_page_response(case_mapping)
345
-
346
- def documentation_pagination_next_page_example(self: Self, case_mapping: Callable) -> Dict[str, Any]:
347
- return self._backend.documentation_pagination_next_page_example(case_mapping)
348
-
349
- def documentation_pagination_parameters(self: Self, case_mapping: Callable) -> List[Tuple[Any]]:
350
- return self._backend.documentation_pagination_parameters(case_mapping)
@@ -1,12 +0,0 @@
1
- class Base:
2
- environment = None
3
- is_cors = False
4
-
5
- def __init__(self, environment):
6
- self.environment = environment
7
-
8
- def configure(self):
9
- pass
10
-
11
- def set_headers_for_input_output(self, input_output):
12
- pass
@@ -1,2 +0,0 @@
1
- from .user import User
2
- from .status import Status
@@ -1,23 +0,0 @@
1
- from collections import OrderedDict
2
- from clearskies import Model
3
- from clearskies.column_types import string, has_many
4
- from clearskies.input_requirements import required, maximum_length
5
- from . import user
6
-
7
-
8
- class Status(Model):
9
- def __init__(self, cursor_backend, columns):
10
- super().__init__(cursor_backend, columns)
11
-
12
- def columns_configuration(self):
13
- return OrderedDict(
14
- [
15
- string("name"),
16
- has_many(
17
- "users",
18
- child_models_class=user.User,
19
- is_readable=True,
20
- readable_child_columns=["status_id", "name", "email"],
21
- ),
22
- ]
23
- )
@@ -1,21 +0,0 @@
1
- from collections import OrderedDict
2
- from clearskies import Model
3
- from clearskies.column_types import belongs_to, email, string, integer, created, updated
4
- from clearskies.input_requirements import required, maximum_length
5
- from . import status
6
-
7
-
8
- class User(Model):
9
- def __init__(self, cursor_backend, columns):
10
- super().__init__(cursor_backend, columns)
11
-
12
- def columns_configuration(self):
13
- return OrderedDict(
14
- [
15
- belongs_to("status_id", parent_models_class=status.Status, input_requirements=[required()]),
16
- string("name", input_requirements=[required(), maximum_length(255)]),
17
- email("email", input_requirements=[required(), maximum_length(255)]),
18
- created("created"),
19
- updated("updated"),
20
- ]
21
- )
@@ -1,64 +0,0 @@
1
- import clearskies
2
- from . import models
3
-
4
-
5
- def restart_user(user_id, input_output):
6
- return {"user_id": user_id}
7
-
8
-
9
- users_api = clearskies.Application(
10
- clearskies.handlers.SimpleRouting,
11
- {
12
- "authentication": clearskies.authentication.public(),
13
- "routes": [
14
- {
15
- "path": "users/{user_id}/restart",
16
- "handler_class": clearskies.handlers.Callable,
17
- "handler_config": {
18
- "callable": restart_user,
19
- },
20
- },
21
- {
22
- "path": "users",
23
- "handler_class": clearskies.handlers.RestfulAPI,
24
- "handler_config": {
25
- "model_class": models.User,
26
- "readable_columns": ["id", "status_id", "name", "email", "created", "updated"],
27
- "writeable_columns": ["status_id", "name", "email"],
28
- "searchable_columns": ["status_id", "name", "email"],
29
- "default_sort_column": "name",
30
- },
31
- },
32
- {
33
- "path": "statuses",
34
- "handler_class": clearskies.handlers.RestfulAPI,
35
- "handler_config": {
36
- "model_class": models.Status,
37
- "read_only": True,
38
- "readable_columns": ["id", "name", "users"],
39
- "searchable_columns": ["name", "users"],
40
- "default_sort_column": "name",
41
- },
42
- },
43
- {
44
- "path": "v1",
45
- "handler_class": clearskies.handlers.SimpleRouting,
46
- "handler_config": {
47
- "routes": [
48
- {
49
- "path": "users",
50
- "handler_class": clearskies.handlers.RestfulAPI,
51
- "handler_config": {
52
- "read_only": True,
53
- "model_class": models.User,
54
- "readable_columns": ["id", "status_id", "name"],
55
- "searchable_columns": ["status_id", "name"],
56
- "default_sort_column": "name",
57
- },
58
- },
59
- ]
60
- },
61
- },
62
- ],
63
- },
64
- )
File without changes
File without changes