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