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
@@ -1,35 +0,0 @@
1
- from .write import Write
2
- from .exceptions import InputError
3
- from collections import OrderedDict
4
- from ..functional import string
5
- import json
6
-
7
-
8
- class Create(Write):
9
- _is_create = True
10
-
11
- def __init__(self, di, logging):
12
- super().__init__(di)
13
- self._logging = logging
14
-
15
- def handle(self, input_output):
16
- model = self._model.empty_model()
17
- input_data = self.request_data(input_output)
18
- self._logging.debug("Incoming request data: " + json.dumps(input_data))
19
- input_errors = {
20
- **self._extra_column_errors(input_data),
21
- **self._find_input_errors(model, input_data, input_output),
22
- }
23
- if input_errors:
24
- self._logging.debug("Request rejected due to input errors: " + json.dumps(input_errors))
25
- raise InputError(input_errors)
26
- model.save(input_data, columns=self._columns)
27
-
28
- return self.success(input_output, self._model_as_json(model, input_output))
29
-
30
- def documentation(self):
31
- nice_model = string.camel_case_to_words(self._model.__class__.__name__)
32
- return self._documentation(
33
- description=f"Create a new {nice_model}",
34
- response_description=f"The new {nice_model}",
35
- )
@@ -1,18 +0,0 @@
1
- from .request_method_routing import RequestMethodRouting
2
- from .create import Create
3
- from .update import Update
4
- from .delete import Delete
5
- from .get import Get
6
-
7
-
8
- class CRUDByMethod(RequestMethodRouting):
9
- def __init__(self, di):
10
- super().__init__(di)
11
-
12
- def method_handler_map(self):
13
- return {
14
- "CREATE": Create,
15
- "GET": Get,
16
- "PATCH": Update,
17
- "DELETE": Delete,
18
- }
@@ -1,32 +0,0 @@
1
- from .base import Base
2
- import os
3
-
4
-
5
- class DatabaseConnector(Base):
6
- _configuration_defaults = {
7
- "tunnel_only": False,
8
- "command": "mysql",
9
- }
10
-
11
- def __init__(self, di):
12
- super().__init__(di)
13
-
14
- def handle(self, input_output):
15
- connection_details = self._di.build("connection_details")
16
- request_body = input_output.json_body(required=False)
17
- if request_body and "tunnel_only" in request_body:
18
- tunnel_only = request_body["tunnel_only"]
19
- else:
20
- tunnel_only = self.configuration("tunnel_only")
21
-
22
- if tunnel_only:
23
- return self.success(input_output, {})
24
-
25
- command = self.configuration("command")
26
- port = connection_details.get("port", 3306)
27
- print("connect!")
28
- print(connection_details["host"])
29
- os.system(
30
- f"{command} -h {connection_details['host']} -u '{connection_details['username']}' -p'{connection_details['password']}' --port={port} -D {connection_details['database']}"
31
- )
32
- print("done!")
@@ -1,61 +0,0 @@
1
- from collections import OrderedDict
2
- from .base import Base
3
- from .. import autodoc
4
- from ..functional import string
5
- from .get import Get
6
-
7
-
8
- class Delete(Get):
9
- _configuration_defaults = {
10
- "model": None,
11
- "model_class": None,
12
- "readable_columns": None,
13
- "where": [],
14
- }
15
-
16
- def __init__(self, di):
17
- super().__init__(di)
18
-
19
- def handle(self, input_output):
20
- model = self.fetch_model(input_output)
21
- if type(model) == str:
22
- return self.error(input_output, model, 404)
23
-
24
- model.delete()
25
- return self.success(input_output, {})
26
-
27
- def documentation(self):
28
- nice_model = string.camel_case_to_words(self._model.__class__.__name__)
29
-
30
- authentication = self.configuration("authentication")
31
- standard_error_responses = []
32
- if not getattr(authentication, "is_public", False):
33
- standard_error_responses.append(self.documentation_access_denied_response())
34
- if getattr(authentication, "can_authorize", False):
35
- standard_error_responses.append(self.documentation_unauthorized_response())
36
-
37
- id_label = "id" if self.configuration("id_column_name") else self.id_column_name
38
- return [
39
- autodoc.request.Request(
40
- "Delete the " + nice_model + " with an " + id_label + " of {" + id_label + "}",
41
- [
42
- self.documentation_success_response(
43
- autodoc.schema.Object("data", children=[]),
44
- description=f"The {nice_model} was deleted",
45
- ),
46
- *standard_error_responses,
47
- self.documentation_not_found(),
48
- ],
49
- relative_path=self.configuration("base_url").rstrip("/") + "/{" + id_label + "}",
50
- parameters=[
51
- autodoc.request.URLPath(
52
- autodoc.schema.Integer(id_label),
53
- description=f"The {id_label} of the record to delete.",
54
- required=True,
55
- )
56
- ],
57
- root_properties={
58
- "security": self.documentation_request_security(),
59
- },
60
- )
61
- ]
@@ -1,5 +0,0 @@
1
- from .authentication import Authentication
2
- from .authorization import Authorization
3
- from .client_error import ClientError
4
- from .input_error import InputError
5
- from .not_found import NotFound
@@ -1,3 +0,0 @@
1
- class NotFound(Exception):
2
- def __init__(self, error):
3
- super().__init__(self, error)
@@ -1,156 +0,0 @@
1
- from .base import Base
2
- from collections import OrderedDict
3
- from .. import autodoc
4
- from .. import condition_parser
5
- from ..functional import string
6
- import inspect
7
-
8
-
9
- class Get(Base):
10
- _model = None
11
-
12
- _configuration_defaults = {
13
- "model": None,
14
- "model_class": None,
15
- "readable_columns": None,
16
- "where": [],
17
- }
18
-
19
- def __init__(self, di):
20
- super().__init__(di)
21
-
22
- def handle(self, input_output):
23
- model = self.fetch_model(input_output)
24
- if type(model) == str:
25
- return self.error(input_output, model, 404)
26
- return self.success(input_output, self._model_as_json(model, input_output))
27
-
28
- def get_model_id(self, input_output):
29
- routing_data = input_output.routing_data()
30
- if self.id_column_name in routing_data:
31
- return routing_data[self.id_column_name]
32
- if "id" in routing_data:
33
- return routing_data["id"]
34
- raise ValueError("I didn't receive the ID in my routing data. I am probably misconfigured.")
35
-
36
- def fetch_model(self, input_output):
37
- id = self.get_model_id(input_output)
38
- models = self._model.where(f"{self.id_column_name}={id}")
39
- for where in self.configuration("where"):
40
- if type(where) == str:
41
- models = models.where(where)
42
- else:
43
- models = self._di.call_function(
44
- where,
45
- models=models,
46
- input_output=input_output,
47
- routing_data=input_output.routing_data(),
48
- authorization_data=input_output.get_authorization_data(),
49
- )
50
- models = models.where_for_request(
51
- models,
52
- input_output.routing_data(),
53
- input_output.get_authorization_data(),
54
- input_output,
55
- )
56
- authorization = self._configuration.get("authorization", None)
57
- if authorization and hasattr(authorization, "filter_models"):
58
- models = authorization.filter_models(models, input_output.get_authorization_data(), input_output)
59
- model = models.first()
60
- if not model.exists:
61
- return "Not Found"
62
-
63
- return model
64
-
65
- def _check_configuration(self, configuration):
66
- super()._check_configuration(configuration)
67
- error_prefix = "Configuration error for %s:" % (self.__class__.__name__)
68
- has_model_class = ("model_class" in configuration) and configuration["model_class"] is not None
69
- has_model = ("model" in configuration) and configuration["model"] is not None
70
- if not has_model and not has_model_class:
71
- raise KeyError(f"{error_prefix} you must specify 'model' or 'model_class'")
72
- if has_model and has_model_class:
73
- raise KeyError(f"{error_prefix} you specified both 'model' and 'model_class', but can only provide one")
74
- if has_model and inspect.isclass(configuration["model"]):
75
- raise ValueError(
76
- "{error_prefix} you must provide a model instance in the 'model' configuration setting, but a class was provided instead"
77
- )
78
- if "where" in configuration:
79
- if not hasattr(configuration["where"], "__iter__") or type(configuration["where"]) == str:
80
- raise ValueError(
81
- f"{error_prefix} 'where' should be an iterable of coditions or callables "
82
- + ", not "
83
- + str(type(configuration["where"])),
84
- )
85
- for index, where in enumerate(configuration["where"]):
86
- if type(where) != str and not callable(where):
87
- raise ValueError(
88
- f"{error_prefix} 'where' entry should be a string with a condition or a callable that filters models "
89
- + f", but entry #{index+1} is neither of these",
90
- )
91
- self._model = self._di.build(configuration["model_class"]) if has_model_class else configuration["model"]
92
- self._columns = self._model.columns(overrides=configuration.get("column_overrides"))
93
-
94
- def _get_readable_columns(self):
95
- resolved_columns = OrderedDict()
96
- for column_name in self.configuration("readable_columns"):
97
- if column_name not in self._columns:
98
- class_name = self.__class__.__name__
99
- model_class = self._model.__class__.__name__
100
- raise ValueError(
101
- f"Handler {class_name} was configured with readable column '{column_name}' but this "
102
- + f"column doesn't exist for model {model_class}"
103
- )
104
- resolved_columns[column_name] = self._columns[column_name]
105
- return resolved_columns
106
-
107
- def documentation(self):
108
- nice_model = string.camel_case_to_words(self._model.__class__.__name__)
109
-
110
- authentication = self.configuration("authentication")
111
- standard_error_responses = []
112
- if not getattr(authentication, "is_public", False):
113
- standard_error_responses.append(self.documentation_access_denied_response())
114
- if getattr(authentication, "can_authorize", False):
115
- standard_error_responses.append(self.documentation_unauthorized_response())
116
-
117
- id_label = "id" if self.configuration("id_column_name") else self.id_column_name
118
-
119
- return [
120
- autodoc.request.Request(
121
- "Fetch the " + nice_model + " with an " + id_label + " of {" + id_label + "}",
122
- [
123
- self.documentation_success_response(
124
- autodoc.schema.Object(
125
- "data",
126
- children=self.documentation_data_schema(),
127
- model_name=string.camel_case_to_snake_case(self._model.__class__.__name__),
128
- ),
129
- description=f"The {nice_model} record",
130
- ),
131
- *standard_error_responses,
132
- self.documentation_not_found(),
133
- ],
134
- relative_path=self.configuration("base_url").rstrip("/") + "/{" + id_label + "}",
135
- parameters=[
136
- autodoc.request.URLPath(
137
- autodoc.schema.String(id_label),
138
- description=f"The {id_label} of the record to get",
139
- required=True,
140
- )
141
- ],
142
- root_properties={
143
- "security": self.documentation_request_security(),
144
- },
145
- )
146
- ]
147
-
148
- def documentation_models(self):
149
- schema_model_name = string.camel_case_to_snake_case(self._model.__class__.__name__)
150
-
151
- return {
152
- schema_model_name: autodoc.schema.Object(
153
- "data",
154
- children=self.documentation_data_schema(),
155
- ),
156
- }
@@ -1,59 +0,0 @@
1
- from .base import Base
2
- from collections import OrderedDict
3
- from .. import autodoc
4
- from .. import condition_parser
5
- from ..functional import string
6
- import inspect
7
-
8
-
9
- class HealthCheck(Base):
10
- _configuration_defaults = {
11
- "services": [],
12
- "callable": None,
13
- }
14
-
15
- def __init__(self, di):
16
- super().__init__(di)
17
-
18
- def top_level_authentication_and_authorization(self, input_output, authentication=None):
19
- pass
20
-
21
- def handle(self, input_output):
22
- services = self.configuration("services")
23
- health_callable = self.configuration("callable")
24
- try:
25
- if services:
26
- for service in services:
27
- self._di.build(service, cache=True)
28
- if health_callable and not health_callable():
29
- return self.respond(input_output, {"status": "failure"}, 500)
30
- except:
31
- return self.respond(input_output, {"status": "failure"}, 500)
32
-
33
- return self.success(input_output, {})
34
-
35
- def _check_configuration(self, configuration):
36
- error_prefix = "Configuration error for %s:" % (self.__class__.__name__)
37
- services = configuration.get("services")
38
- if services is not None and type(services) != list:
39
- raise ValueError(
40
- f'{error_prefix} "services" should be a list of names, with each name corresponding to a dependency to load'
41
- )
42
- health_callable = configuration.get("callable")
43
- if health_callable is not None and not callable(health_callable):
44
- raise ValueError(
45
- f'{error_prefix} "callable" should be a callable that returns true/false to denote health status'
46
- )
47
-
48
- def documentation(self):
49
- return [
50
- autodoc.request.Request(
51
- "Healthcheck",
52
- [
53
- self.documentation_success_response(
54
- autodoc.schema.Object("data", children=[]),
55
- ),
56
- ],
57
- relative_path=self.configuration("base_url"),
58
- )
59
- ]
@@ -1,79 +0,0 @@
1
- from .exceptions import InputError
2
- from collections import OrderedDict
3
- from abc import abstractmethod
4
-
5
-
6
- class InputProcessing:
7
- _is_create = False
8
-
9
- def _get_writeable_columns(self):
10
- if self._writeable_columns is None:
11
- self._writeable_columns = self._get_rw_columns("writeable")
12
- additional_columns = OrderedDict()
13
- for column in self._writeable_columns.values():
14
- more_columns = column.additional_write_columns(is_create=self._is_create)
15
- for additional_column_name, additional_column in more_columns.items():
16
- additional_columns[additional_column_name] = additional_column
17
- for additional_column_name, additional_column in additional_columns.items():
18
- self._writeable_columns[additional_column_name] = additional_column
19
- return self._writeable_columns
20
-
21
- def _extra_column_errors(self, input_data):
22
- input_errors = {}
23
- allowed = self._get_writeable_columns()
24
- for column_name in input_data.keys():
25
- if column_name not in allowed:
26
- input_errors[column_name] = f"Input column '{column_name}' is not an allowed column"
27
- return input_errors
28
-
29
- def _find_input_errors(self, model, input_data, input_output):
30
- input_errors = {}
31
- for column in self._get_writeable_columns().values():
32
- input_errors = {
33
- **input_errors,
34
- **column.input_errors(model, input_data),
35
- }
36
- input_error_callable = self.configuration("input_error_callable")
37
- if input_error_callable:
38
- more_input_errors = self._di.call_function(
39
- input_error_callable,
40
- input_data=input_data,
41
- request_data=input_data,
42
- input_output=input_output,
43
- routing_data=input_output.routing_data(),
44
- authorization_data=input_output.get_authorization_data(),
45
- )
46
- if type(more_input_errors) != dict:
47
- raise ValueError(
48
- "The input error callable, '"
49
- + str(input_error_callable)
50
- + "', did not return a dictionary as required"
51
- )
52
- input_errors = {
53
- **input_errors,
54
- **more_input_errors,
55
- }
56
- return input_errors
57
-
58
- def request_data(self, input_output, required=True):
59
- # we have to map from internal names to external names, because case mapping
60
- # isn't always one-to-one, so we want to do it exactly the same way that the documentation
61
- # is built.
62
- key_map = {self.auto_case_column_name(key, True): key for key in self._get_writeable_columns().keys()}
63
- # in case the id comes up in the request body
64
- key_map[self.auto_case_internal_column_name("id")] = "id"
65
-
66
- # and make sure we don't drop any data along the way, because the input validation
67
- # needs to return an error for unexpected data.
68
- request_data = {
69
- key_map.get(key, key): value for (key, value) in input_output.request_data(required=required).items()
70
- }
71
- # the parent handler should provide our resource id (we don't do any routing ourselves)
72
- # However, our update/etc handlers need to find the id easily, so I'm going to be lazy and
73
- # just dump it into the request. I'll probably regret that.
74
- routing_data = input_output.routing_data()
75
- # we don't have to worry about casing on the 'id' in routing_data because it doesn't come in from the
76
- # route with a name. Rather, it is populated by clearskies, so will always just be 'id'
77
- if "id" in routing_data:
78
- request_data["id"] = routing_data["id"]
79
- return request_data