clear-skies 2.0.15__tar.gz → 2.0.16__tar.gz

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 (278) hide show
  1. {clear_skies-2.0.15 → clear_skies-2.0.16}/CHANGELOG.md +15 -0
  2. clear_skies-2.0.16/LATEST_CHANGELOG.md +11 -0
  3. {clear_skies-2.0.15 → clear_skies-2.0.16}/PKG-INFO +1 -1
  4. {clear_skies-2.0.15 → clear_skies-2.0.16}/pyproject.toml +1 -1
  5. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/backends/api_backend.py +31 -19
  6. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/belongs_to_model.py +1 -1
  7. clear_skies-2.0.16/src/clearskies/functional/json.py +47 -0
  8. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/akeyless.py +4 -24
  9. {clear_skies-2.0.15 → clear_skies-2.0.16}/uv.lock +1 -1
  10. clear_skies-2.0.15/LATEST_CHANGELOG.md +0 -5
  11. {clear_skies-2.0.15 → clear_skies-2.0.16}/.editorconfig +0 -0
  12. {clear_skies-2.0.15 → clear_skies-2.0.16}/.github/workflows/create-version.yaml +0 -0
  13. {clear_skies-2.0.15 → clear_skies-2.0.16}/.github/workflows/docs.yaml +0 -0
  14. {clear_skies-2.0.15 → clear_skies-2.0.16}/.github/workflows/run-tests.yml +0 -0
  15. {clear_skies-2.0.15 → clear_skies-2.0.16}/.github/workflows/tests-matrix.yaml +0 -0
  16. {clear_skies-2.0.15 → clear_skies-2.0.16}/.github/workflows/tests.yaml +0 -0
  17. {clear_skies-2.0.15 → clear_skies-2.0.16}/.gitignore +0 -0
  18. {clear_skies-2.0.15 → clear_skies-2.0.16}/.pre-commit-config.yaml +0 -0
  19. {clear_skies-2.0.15 → clear_skies-2.0.16}/.python-version +0 -0
  20. {clear_skies-2.0.15 → clear_skies-2.0.16}/.vscode/extensions.json +0 -0
  21. {clear_skies-2.0.15 → clear_skies-2.0.16}/.vscode/settings.json +0 -0
  22. {clear_skies-2.0.15 → clear_skies-2.0.16}/LICENSE +0 -0
  23. {clear_skies-2.0.15 → clear_skies-2.0.16}/README.md +0 -0
  24. {clear_skies-2.0.15 → clear_skies-2.0.16}/build.sh +0 -0
  25. {clear_skies-2.0.15 → clear_skies-2.0.16}/cliff.toml +0 -0
  26. {clear_skies-2.0.15 → clear_skies-2.0.16}/ruff.toml +0 -0
  27. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/__init__.py +0 -0
  28. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/action.py +0 -0
  29. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/__init__.py +0 -0
  30. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/authentication.py +0 -0
  31. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/authorization.py +0 -0
  32. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/authorization_pass_through.py +0 -0
  33. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/jwks.py +0 -0
  34. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/public.py +0 -0
  35. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/authentication/secret_bearer.py +0 -0
  36. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/__init__.py +0 -0
  37. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/__init__.py +0 -0
  38. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/__init__.py +0 -0
  39. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/oai3_json.py +0 -0
  40. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/oai3_schema_resolver.py +0 -0
  41. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/parameter.py +0 -0
  42. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/request.py +0 -0
  43. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/response.py +0 -0
  44. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/schema/__init__.py +0 -0
  45. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/schema/array.py +0 -0
  46. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/schema/default.py +0 -0
  47. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/schema/enum.py +0 -0
  48. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/schema/object.py +0 -0
  49. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/formats/oai3_json/test.json +0 -0
  50. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/py.typed +0 -0
  51. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/__init__.py +0 -0
  52. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/header.py +0 -0
  53. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/json_body.py +0 -0
  54. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/parameter.py +0 -0
  55. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/request.py +0 -0
  56. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/url_parameter.py +0 -0
  57. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/request/url_path.py +0 -0
  58. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/response/__init__.py +0 -0
  59. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/response/response.py +0 -0
  60. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/__init__.py +0 -0
  61. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/array.py +0 -0
  62. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/base64.py +0 -0
  63. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/boolean.py +0 -0
  64. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/date.py +0 -0
  65. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/datetime.py +0 -0
  66. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/double.py +0 -0
  67. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/enum.py +0 -0
  68. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/integer.py +0 -0
  69. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/long.py +0 -0
  70. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/number.py +0 -0
  71. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/object.py +0 -0
  72. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/password.py +0 -0
  73. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/schema.py +0 -0
  74. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/autodoc/schema/string.py +0 -0
  75. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/backends/__init__.py +0 -0
  76. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/backends/backend.py +0 -0
  77. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/backends/cursor_backend.py +0 -0
  78. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/backends/memory_backend.py +0 -0
  79. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/backends/secrets_backend.py +0 -0
  80. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/column.py +0 -0
  81. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/__init__.py +0 -0
  82. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/audit.py +0 -0
  83. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/belongs_to_id.py +0 -0
  84. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/belongs_to_self.py +0 -0
  85. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/boolean.py +0 -0
  86. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/category_tree.py +0 -0
  87. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/category_tree_ancestors.py +0 -0
  88. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/category_tree_children.py +0 -0
  89. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/category_tree_descendants.py +0 -0
  90. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/created.py +0 -0
  91. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/created_by_authorization_data.py +0 -0
  92. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/created_by_header.py +0 -0
  93. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/created_by_ip.py +0 -0
  94. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/created_by_routing_data.py +0 -0
  95. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/created_by_user_agent.py +0 -0
  96. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/date.py +0 -0
  97. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/datetime.py +0 -0
  98. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/email.py +0 -0
  99. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/float.py +0 -0
  100. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/has_many.py +0 -0
  101. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/has_many_self.py +0 -0
  102. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/has_one.py +0 -0
  103. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/integer.py +0 -0
  104. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/json.py +0 -0
  105. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/many_to_many_ids.py +0 -0
  106. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/many_to_many_ids_with_data.py +0 -0
  107. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/many_to_many_models.py +0 -0
  108. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/many_to_many_pivots.py +0 -0
  109. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/phone.py +0 -0
  110. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/select.py +0 -0
  111. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/string.py +0 -0
  112. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/timestamp.py +0 -0
  113. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/updated.py +0 -0
  114. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/columns/uuid.py +0 -0
  115. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/README.md +0 -0
  116. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/__init__.py +0 -0
  117. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/actions.py +0 -0
  118. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/any.py +0 -0
  119. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/any_dict.py +0 -0
  120. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/any_dict_or_callable.py +0 -0
  121. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/authentication.py +0 -0
  122. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/authorization.py +0 -0
  123. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/boolean.py +0 -0
  124. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/boolean_or_callable.py +0 -0
  125. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/callable_config.py +0 -0
  126. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/columns.py +0 -0
  127. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/conditions.py +0 -0
  128. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/config.py +0 -0
  129. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/datetime.py +0 -0
  130. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/datetime_or_callable.py +0 -0
  131. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/email.py +0 -0
  132. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/email_list.py +0 -0
  133. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/email_list_or_callable.py +0 -0
  134. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/email_or_email_list_or_callable.py +0 -0
  135. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/endpoint.py +0 -0
  136. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/endpoint_list.py +0 -0
  137. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/float.py +0 -0
  138. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/float_or_callable.py +0 -0
  139. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/headers.py +0 -0
  140. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/integer.py +0 -0
  141. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/integer_or_callable.py +0 -0
  142. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/joins.py +0 -0
  143. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/list_any_dict.py +0 -0
  144. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/list_any_dict_or_callable.py +0 -0
  145. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/model_class.py +0 -0
  146. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/model_column.py +0 -0
  147. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/model_columns.py +0 -0
  148. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/model_destination_name.py +0 -0
  149. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/model_to_id_column.py +0 -0
  150. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/readable_model_column.py +0 -0
  151. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/readable_model_columns.py +0 -0
  152. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/schema.py +0 -0
  153. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/searchable_model_columns.py +0 -0
  154. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/security_headers.py +0 -0
  155. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/select.py +0 -0
  156. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/select_list.py +0 -0
  157. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/string.py +0 -0
  158. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/string_dict.py +0 -0
  159. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/string_list.py +0 -0
  160. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/string_list_or_callable.py +0 -0
  161. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/string_or_callable.py +0 -0
  162. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/timedelta.py +0 -0
  163. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/timezone.py +0 -0
  164. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/url.py +0 -0
  165. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/validators.py +0 -0
  166. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/writeable_model_column.py +0 -0
  167. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configs/writeable_model_columns.py +0 -0
  168. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/configurable.py +0 -0
  169. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/contexts/__init__.py +0 -0
  170. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/contexts/cli.py +0 -0
  171. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/contexts/context.py +0 -0
  172. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/contexts/wsgi.py +0 -0
  173. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/contexts/wsgi_ref.py +0 -0
  174. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/decorators.py +0 -0
  175. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/decorators.pyi +0 -0
  176. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/__init__.py +0 -0
  177. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/additional_config.py +0 -0
  178. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/additional_config_auto_import.py +0 -0
  179. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/di.py +0 -0
  180. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/__init__.py +0 -0
  181. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/akeyless_sdk.py +0 -0
  182. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/by_class.py +0 -0
  183. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/by_name.py +0 -0
  184. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/di.py +0 -0
  185. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/environment.py +0 -0
  186. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/input_output.py +0 -0
  187. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/now.py +0 -0
  188. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/requests.py +0 -0
  189. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/secrets.py +0 -0
  190. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/utcnow.py +0 -0
  191. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/inject/uuid.py +0 -0
  192. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/injectable.py +0 -0
  193. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/injectable_properties.py +0 -0
  194. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/test_module/__init__.py +0 -0
  195. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/test_module/another_module/__init__.py +0 -0
  196. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/di/test_module/module_class.py +0 -0
  197. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/end.py +0 -0
  198. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoint.py +0 -0
  199. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoint_group.py +0 -0
  200. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/__init__.py +0 -0
  201. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/advanced_search.py +0 -0
  202. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/callable.py +0 -0
  203. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/create.py +0 -0
  204. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/delete.py +0 -0
  205. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/get.py +0 -0
  206. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/health_check.py +0 -0
  207. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/list.py +0 -0
  208. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/restful_api.py +0 -0
  209. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/schema.py +0 -0
  210. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/simple_search.py +0 -0
  211. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/endpoints/update.py +0 -0
  212. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/environment.py +0 -0
  213. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/__init__.py +0 -0
  214. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/authentication.py +0 -0
  215. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/authorization.py +0 -0
  216. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/client_error.py +0 -0
  217. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/input_errors.py +0 -0
  218. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/missing_dependency.py +0 -0
  219. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/moved_permanently.py +0 -0
  220. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/moved_temporarily.py +0 -0
  221. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/exceptions/not_found.py +0 -0
  222. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/functional/__init__.py +0 -0
  223. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/functional/routing.py +0 -0
  224. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/functional/string.py +0 -0
  225. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/functional/validations.py +0 -0
  226. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/__init__.py +0 -0
  227. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/cli.py +0 -0
  228. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/exceptions/__init__.py +0 -0
  229. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/exceptions/cli_input_error.py +0 -0
  230. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/exceptions/cli_not_found.py +0 -0
  231. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/headers.py +0 -0
  232. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/input_output.py +0 -0
  233. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/programmatic.py +0 -0
  234. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/py.typed +0 -0
  235. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/input_outputs/wsgi.py +0 -0
  236. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/model.py +0 -0
  237. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/py.typed +0 -0
  238. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/query/__init__.py +0 -0
  239. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/query/condition.py +0 -0
  240. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/query/join.py +0 -0
  241. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/query/query.py +0 -0
  242. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/query/sort.py +0 -0
  243. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/schema.py +0 -0
  244. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/__init__.py +0 -0
  245. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/additional_configs/__init__.py +0 -0
  246. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py +0 -0
  247. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +0 -0
  248. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/exceptions/__init__.py +0 -0
  249. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/exceptions/not_found_error.py +0 -0
  250. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/exceptions/permissions_error.py +0 -0
  251. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/secrets/secrets.py +0 -0
  252. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_header.py +0 -0
  253. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/__init__.py +0 -0
  254. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/cache_control.py +0 -0
  255. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/cors.py +0 -0
  256. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/csp.py +0 -0
  257. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/hsts.py +0 -0
  258. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/x_content_type_options.py +0 -0
  259. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/security_headers/x_frame_options.py +0 -0
  260. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/test_base.py +0 -0
  261. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/typing.py +0 -0
  262. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validator.py +0 -0
  263. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/__init__.py +0 -0
  264. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/after_column.py +0 -0
  265. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/before_column.py +0 -0
  266. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/in_the_future.py +0 -0
  267. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/in_the_future_at_least.py +0 -0
  268. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/in_the_future_at_most.py +0 -0
  269. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/in_the_past.py +0 -0
  270. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/in_the_past_at_least.py +0 -0
  271. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/in_the_past_at_most.py +0 -0
  272. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/maximum_length.py +0 -0
  273. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/maximum_value.py +0 -0
  274. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/minimum_length.py +0 -0
  275. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/minimum_value.py +0 -0
  276. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/required.py +0 -0
  277. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/timedelta.py +0 -0
  278. {clear_skies-2.0.15 → clear_skies-2.0.16}/src/clearskies/validators/unique.py +0 -0
@@ -5,8 +5,22 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [2.0.16] - 2025-10-16
9
+
10
+ ### Added
11
+ - Add json attribute to api backend by @cmancone in [#30](https://github.com/clearskies-py/clearskies/pull/30)
12
+ - Add json attribute to api backend
13
+
14
+ ### Fixed
15
+ - Reorder map_records_response
16
+ - Reorder mapping steps
17
+ - Use empty instead of empty_model
18
+
8
19
  ## [2.0.15] - 2025-10-16
9
20
 
21
+ ### Changed
22
+ - Bump version to v2.0.15 by @github-actions[bot]
23
+
10
24
  ### Removed
11
25
  - Remove unused imports by @tnijboer in [#29](https://github.com/clearskies-py/clearskies/pull/29)
12
26
 
@@ -838,6 +852,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
838
852
  * @ made their first contribution
839
853
  * @tnijboer made their first contribution
840
854
  * @conormancone-cimpress made their first contribution
855
+ [2.0.16]: https://github.com/clearskies-py/clearskies/compare/v2.0.15..v2.0.16
841
856
  [2.0.15]: https://github.com/clearskies-py/clearskies/compare/v2.0.14..v2.0.15
842
857
  [2.0.14]: https://github.com/clearskies-py/clearskies/compare/v2.0.13..v2.0.14
843
858
  [2.0.13]: https://github.com/clearskies-py/clearskies/compare/v2.0.12..v2.0.13
@@ -0,0 +1,11 @@
1
+ ## [2.0.16] - 2025-10-16
2
+
3
+ ### Added
4
+ - Add json attribute to api backend by @cmancone in [#30](https://github.com/clearskies-py/clearskies/pull/30)
5
+ - Add json attribute to api backend
6
+
7
+ ### Fixed
8
+ - Reorder map_records_response
9
+ - Reorder mapping steps
10
+ - Use empty instead of empty_model
11
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: clear-skies
3
- Version: 2.0.15
3
+ Version: 2.0.16
4
4
  Summary: A framework for building backends in the cloud
5
5
  Project-URL: Documentation, https://clearskies.io/
6
6
  Project-URL: Repository, https://github.com/clearskies-py/clearskies
@@ -1,7 +1,7 @@
1
1
  [project]
2
2
  name = "clear-skies"
3
3
  description = "A framework for building backends in the cloud"
4
- version = "2.0.15"
4
+ version = "2.0.16"
5
5
  license = "MIT"
6
6
  readme = "./README.md"
7
7
  authors = [{name = "Conor Mancone", email = "cmancone@gmail.com"}]
@@ -11,6 +11,7 @@ from clearskies.autodoc.schema import Schema as AutoDocSchema
11
11
  from clearskies.autodoc.schema import String as AutoDocString
12
12
  from clearskies.backends.backend import Backend
13
13
  from clearskies.di import InjectableProperties, inject
14
+ from clearskies.functional import json as json_functional
14
15
  from clearskies.functional import routing, string
15
16
 
16
17
  if TYPE_CHECKING:
@@ -550,7 +551,7 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
550
551
  }
551
552
  ```
552
553
  """
553
- api_to_model_map = configs.StringDict(default={})
554
+ api_to_model_map = configs.AnyDict(default={})
554
555
 
555
556
  """
556
557
  The name of the pagination parameter
@@ -589,7 +590,7 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
589
590
  authentication: Authentication | None = None,
590
591
  model_casing: str = "snake_case",
591
592
  api_casing: str = "snake_case",
592
- api_to_model_map: dict[str, str] = {},
593
+ api_to_model_map: dict[str, str | list[str]] = {},
593
594
  pagination_parameter_name: str = "start",
594
595
  pagination_parameter_type: str = "str",
595
596
  limit_parameter_name: str = "limit",
@@ -897,16 +898,16 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
897
898
  f"The response from a records request returned a variable of type {response_data.__class__.__name__}, which is just confusing. To do automatic introspection, I need a list or a dictionary. I'm afraid you'll have to extend the API backend and override the map_record_response method to deal with this."
898
899
  )
899
900
 
900
- for key, value in response_data.items():
901
- if not isinstance(value, list):
902
- continue
903
- return self.map_records_response(value, query, query_data)
904
-
905
901
  # a records request may only return a single record, so before we fail, let's check for that
906
902
  record = self.check_dict_and_map_to_model(response_data, columns, query_data)
907
903
  if record is not None:
908
904
  return [record]
909
905
 
906
+ for key, value in response_data.items():
907
+ if not isinstance(value, list):
908
+ continue
909
+ return self.map_records_response(value, query, query_data)
910
+
910
911
  raise ValueError(
911
912
  "The response from a records request returned a dictionary, but none of the items in the dictionary was a list, so I don't know where to find the records. I only ever check one level deep in dictionaries. I'm afraid you'll have to extend the API backend and override the map_records_response method to deal with this."
912
913
  )
@@ -958,27 +959,38 @@ class ApiBackend(configurable.Configurable, Backend, InjectableProperties):
958
959
  map_keys = set(response_to_model_map.keys())
959
960
  matching = response_keys.intersection(map_keys)
960
961
 
961
- # if nothing matches then clearly this isn't what we're looking for: repeat on all the children
962
- if not matching:
963
- for key, value in response_data.items():
964
- if not isinstance(value, dict):
965
- continue
966
- mapped = self.check_dict_and_map_to_model(value, columns)
967
- if mapped:
968
- return {**query_data, **mapped}
969
-
970
- # no match anywhere :(
971
- return None
972
-
973
962
  # we may need to be smarter about whether or not we think we found a match, but for now let's
974
963
  # ignore that possibility. If any columns match between the keys in our response dictionary and
975
964
  # the keys that we are expecting to find data in, then just assume that we have found a record.
976
965
  mapped = {response_to_model_map[key]: response_data[key] for key in matching}
977
966
 
967
+ for api_key, column_name in self.api_to_model_map.items():
968
+ if not "." in api_key:
969
+ continue
970
+ value = json_functional.get_nested_attribute(response_data, api_key)
971
+ if value is None:
972
+ continue
973
+ if isinstance(column_name, list):
974
+ for column in column_name:
975
+ mapped[column] = value
976
+ else:
977
+ mapped[column_name] = value
978
978
  # finally, move over anything not mentioned in the map
979
979
  for key in response_keys.difference(map_keys):
980
980
  mapped[string.swap_casing(key, self.api_casing, self.model_casing)] = response_data[key]
981
981
 
982
+ # if nothing matches then clearly this isn't what we're looking for: repeat on all the children
983
+ if not mapped:
984
+ for key, value in response_data.items():
985
+ if not isinstance(value, dict):
986
+ continue
987
+ remapped = self.check_dict_and_map_to_model(value, columns)
988
+ if remapped:
989
+ return {**query_data, **remapped}
990
+
991
+ # no match anywhere :(
992
+ return None
993
+
982
994
  return {**query_data, **mapped}
983
995
 
984
996
  def build_response_to_model_map(self, columns: dict[str, Column]) -> dict[str, str]:
@@ -65,7 +65,7 @@ class BelongsToModel(Column):
65
65
  parent_class = belongs_to_column.parent_model_class
66
66
  parent_model = self.di.build(parent_class, cache=False)
67
67
  if not parent_id:
68
- return parent_model.empty_model()
68
+ return parent_model.empty()
69
69
 
70
70
  parent_id_column_name = parent_model.id_column_name
71
71
  join_alias = belongs_to_column.join_table_alias()
@@ -0,0 +1,47 @@
1
+ from typing import Any, cast
2
+
3
+
4
+ def get_nested_attribute(data: dict[str, Any] | str, attr_path: str) -> Any:
5
+ """
6
+ Extract a nested attribute from JSON data using dot notation.
7
+
8
+ This function navigates through a nested JSON structure using a dot-separated path
9
+ to retrieve a specific attribute. If the input is a string, it will attempt to parse
10
+ it as JSON first.
11
+
12
+ Example:
13
+ ```
14
+ data = {"database": {"credentials": {"username": "admin", "password": "secret"}}}
15
+ username = get_nested_attribute(data, "database.credentials.username")
16
+ # Returns "admin"
17
+ ```
18
+
19
+ Args:
20
+ data: The JSON data as a dictionary or a JSON string
21
+ attr_path: The path to the attribute using dot notation (e.g., "database.username")
22
+
23
+ Returns:
24
+ The value at the specified path
25
+
26
+ Raises:
27
+ ValueError: If the data cannot be parsed as JSON
28
+ KeyError: If the attribute path doesn't exist in the data
29
+ """
30
+ keys = attr_path.split(".", 1)
31
+ if not isinstance(data, dict):
32
+ try:
33
+ import json
34
+
35
+ data = json.loads(data)
36
+ except Exception:
37
+ raise ValueError(f"Could not parse data as JSON to get attribute '{attr_path}'")
38
+
39
+ # At this point, we know data is a dictionary
40
+ data_dict = cast(dict[str, Any], data) # Help type checker understand data is a dict
41
+
42
+ if len(keys) == 1:
43
+ if keys[0] not in data_dict:
44
+ raise KeyError(f"Data does not contain attribute '{attr_path}'")
45
+ return data_dict[keys[0]]
46
+
47
+ return get_nested_attribute(data_dict[keys[0]], keys[1])
@@ -1,7 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import datetime
4
- import json
5
4
  import logging
6
5
  from types import ModuleType
7
6
  from typing import TYPE_CHECKING, Any
@@ -9,6 +8,7 @@ from typing import TYPE_CHECKING, Any
9
8
  from clearskies import configs, secrets
10
9
  from clearskies.decorators import parameters_to_properties
11
10
  from clearskies.di import inject
11
+ from clearskies.functional.json import get_nested_attribute
12
12
  from clearskies.secrets.exceptions import PermissionsError
13
13
 
14
14
  if TYPE_CHECKING:
@@ -224,7 +224,7 @@ class Akeyless(secrets.Secrets):
224
224
  raise KeyError(f"Secret '{path}' not found")
225
225
  raise e
226
226
  if json_attribute:
227
- return self._get_nested_attribute(res[path], json_attribute) # type: ignore
227
+ return get_nested_attribute(res[path], json_attribute) # type: ignore
228
228
  return str(res[path])
229
229
 
230
230
  def get_dynamic_secret(
@@ -249,7 +249,7 @@ class Akeyless(secrets.Secrets):
249
249
  kwargs["args"] = args # type: ignore
250
250
  res: dict[str, Any] = self.api.get_dynamic_secret_value(self.akeyless.GetDynamicSecretValue(**kwargs)) # type: ignore
251
251
  if json_attribute:
252
- return self._get_nested_attribute(res, json_attribute)
252
+ return get_nested_attribute(res, json_attribute)
253
253
  return res
254
254
 
255
255
  def get_rotated_secret(
@@ -276,7 +276,7 @@ class Akeyless(secrets.Secrets):
276
276
 
277
277
  res: dict[str, str] = self._api.get_rotated_secret_value(self.akeyless.GetRotatedSecretValue(**kwargs))["value"] # type: ignore
278
278
  if json_attribute:
279
- return self._get_nested_attribute(res, json_attribute)
279
+ return get_nested_attribute(res, json_attribute)
280
280
  return res
281
281
 
282
282
  def describe_secret(self, path: str) -> Any:
@@ -470,26 +470,6 @@ class Akeyless(secrets.Secrets):
470
470
  self.akeyless.DescribePermissions(token=self._get_token(), path=path, type=type)
471
471
  ).client_permissions # type: ignore
472
472
 
473
- def _get_nested_attribute(self, data: dict[str, Any] | str, attr_path: str) -> Any:
474
- """
475
- Extract a nested attribute from JSON data.
476
-
477
- Parses the provided data as JSON if it's a string. Traverses the nested structure using
478
- the dot-separated path (e.g., "database.username"). Raises ValueError if the data cannot
479
- be parsed as JSON, or KeyError if the attribute path doesn't exist in the data.
480
- """
481
- keys = attr_path.split(".", 1)
482
- if not isinstance(data, dict):
483
- try:
484
- data = json.loads(data)
485
- except Exception:
486
- raise ValueError(f"Could not parse secret as JSON to get attribute '{attr_path}'")
487
- if len(keys) == 1:
488
- if not isinstance(data, dict) or keys[0] not in data:
489
- raise KeyError(f"Secret does not contain attribute '{attr_path}'")
490
- return data[keys[0]] # type: ignore
491
- return self._get_nested_attribute(data[keys[0]], keys[1]) # type: ignore
492
-
493
473
 
494
474
  class AkeylessSaml(Akeyless):
495
475
  """Convenience class for SAML authentication with Akeyless."""
@@ -202,7 +202,7 @@ wheels = [
202
202
 
203
203
  [[package]]
204
204
  name = "clear-skies"
205
- version = "2.0.15"
205
+ version = "2.0.16"
206
206
  source = { editable = "." }
207
207
  dependencies = [
208
208
  { name = "dateparser" },
@@ -1,5 +0,0 @@
1
- ## [2.0.15] - 2025-10-16
2
-
3
- ### Removed
4
- - Remove unused imports by @tnijboer in [#29](https://github.com/clearskies-py/clearskies/pull/29)
5
-
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes