clear-skies 2.0.3__py3-none-any.whl → 2.0.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of clear-skies might be problematic. Click here for more details.
- clear_skies-2.0.5.dist-info/METADATA +74 -0
- clear_skies-2.0.5.dist-info/RECORD +4 -0
- {clear_skies-2.0.3.dist-info → clear_skies-2.0.5.dist-info}/WHEEL +1 -1
- clear_skies-2.0.3.dist-info/METADATA +0 -46
- clear_skies-2.0.3.dist-info/RECORD +0 -249
- clearskies/__init__.py +0 -59
- clearskies/action.py +0 -7
- clearskies/authentication/__init__.py +0 -15
- clearskies/authentication/authentication.py +0 -46
- clearskies/authentication/authorization.py +0 -16
- clearskies/authentication/authorization_pass_through.py +0 -20
- clearskies/authentication/jwks.py +0 -163
- clearskies/authentication/public.py +0 -5
- clearskies/authentication/secret_bearer.py +0 -553
- clearskies/autodoc/__init__.py +0 -8
- clearskies/autodoc/formats/__init__.py +0 -5
- clearskies/autodoc/formats/oai3_json/__init__.py +0 -7
- clearskies/autodoc/formats/oai3_json/oai3_json.py +0 -87
- clearskies/autodoc/formats/oai3_json/oai3_schema_resolver.py +0 -15
- clearskies/autodoc/formats/oai3_json/parameter.py +0 -35
- clearskies/autodoc/formats/oai3_json/request.py +0 -68
- clearskies/autodoc/formats/oai3_json/response.py +0 -28
- clearskies/autodoc/formats/oai3_json/schema/__init__.py +0 -11
- clearskies/autodoc/formats/oai3_json/schema/array.py +0 -9
- clearskies/autodoc/formats/oai3_json/schema/default.py +0 -13
- clearskies/autodoc/formats/oai3_json/schema/enum.py +0 -7
- clearskies/autodoc/formats/oai3_json/schema/object.py +0 -29
- clearskies/autodoc/formats/oai3_json/test.json +0 -1985
- clearskies/autodoc/py.typed +0 -0
- clearskies/autodoc/request/__init__.py +0 -15
- clearskies/autodoc/request/header.py +0 -6
- clearskies/autodoc/request/json_body.py +0 -6
- clearskies/autodoc/request/parameter.py +0 -8
- clearskies/autodoc/request/request.py +0 -38
- clearskies/autodoc/request/url_parameter.py +0 -6
- clearskies/autodoc/request/url_path.py +0 -6
- clearskies/autodoc/response/__init__.py +0 -5
- clearskies/autodoc/response/response.py +0 -9
- clearskies/autodoc/schema/__init__.py +0 -31
- clearskies/autodoc/schema/array.py +0 -10
- clearskies/autodoc/schema/base64.py +0 -8
- clearskies/autodoc/schema/boolean.py +0 -5
- clearskies/autodoc/schema/date.py +0 -5
- clearskies/autodoc/schema/datetime.py +0 -5
- clearskies/autodoc/schema/double.py +0 -5
- clearskies/autodoc/schema/enum.py +0 -17
- clearskies/autodoc/schema/integer.py +0 -6
- clearskies/autodoc/schema/long.py +0 -5
- clearskies/autodoc/schema/number.py +0 -6
- clearskies/autodoc/schema/object.py +0 -13
- clearskies/autodoc/schema/password.py +0 -5
- clearskies/autodoc/schema/schema.py +0 -11
- clearskies/autodoc/schema/string.py +0 -5
- clearskies/backends/__init__.py +0 -65
- clearskies/backends/api_backend.py +0 -1178
- clearskies/backends/backend.py +0 -136
- clearskies/backends/cursor_backend.py +0 -335
- clearskies/backends/memory_backend.py +0 -797
- clearskies/backends/secrets_backend.py +0 -106
- clearskies/column.py +0 -1233
- clearskies/columns/__init__.py +0 -71
- clearskies/columns/audit.py +0 -206
- clearskies/columns/belongs_to_id.py +0 -483
- clearskies/columns/belongs_to_model.py +0 -132
- clearskies/columns/belongs_to_self.py +0 -105
- clearskies/columns/boolean.py +0 -113
- clearskies/columns/category_tree.py +0 -275
- clearskies/columns/category_tree_ancestors.py +0 -51
- clearskies/columns/category_tree_children.py +0 -127
- clearskies/columns/category_tree_descendants.py +0 -48
- clearskies/columns/created.py +0 -95
- clearskies/columns/created_by_authorization_data.py +0 -116
- clearskies/columns/created_by_header.py +0 -99
- clearskies/columns/created_by_ip.py +0 -92
- clearskies/columns/created_by_routing_data.py +0 -97
- clearskies/columns/created_by_user_agent.py +0 -92
- clearskies/columns/date.py +0 -234
- clearskies/columns/datetime.py +0 -282
- clearskies/columns/email.py +0 -76
- clearskies/columns/float.py +0 -153
- clearskies/columns/has_many.py +0 -505
- clearskies/columns/has_many_self.py +0 -56
- clearskies/columns/has_one.py +0 -14
- clearskies/columns/integer.py +0 -160
- clearskies/columns/json.py +0 -126
- clearskies/columns/many_to_many_ids.py +0 -337
- clearskies/columns/many_to_many_ids_with_data.py +0 -274
- clearskies/columns/many_to_many_models.py +0 -158
- clearskies/columns/many_to_many_pivots.py +0 -134
- clearskies/columns/phone.py +0 -159
- clearskies/columns/select.py +0 -92
- clearskies/columns/string.py +0 -102
- clearskies/columns/timestamp.py +0 -164
- clearskies/columns/updated.py +0 -110
- clearskies/columns/uuid.py +0 -86
- clearskies/configs/README.md +0 -105
- clearskies/configs/__init__.py +0 -162
- clearskies/configs/actions.py +0 -43
- clearskies/configs/any.py +0 -13
- clearskies/configs/any_dict.py +0 -22
- clearskies/configs/any_dict_or_callable.py +0 -23
- clearskies/configs/authentication.py +0 -23
- clearskies/configs/authorization.py +0 -23
- clearskies/configs/boolean.py +0 -16
- clearskies/configs/boolean_or_callable.py +0 -18
- clearskies/configs/callable_config.py +0 -18
- clearskies/configs/columns.py +0 -34
- clearskies/configs/conditions.py +0 -30
- clearskies/configs/config.py +0 -24
- clearskies/configs/datetime.py +0 -18
- clearskies/configs/datetime_or_callable.py +0 -19
- clearskies/configs/endpoint.py +0 -23
- clearskies/configs/endpoint_list.py +0 -28
- clearskies/configs/float.py +0 -16
- clearskies/configs/float_or_callable.py +0 -18
- clearskies/configs/integer.py +0 -16
- clearskies/configs/integer_or_callable.py +0 -18
- clearskies/configs/joins.py +0 -30
- clearskies/configs/list_any_dict.py +0 -30
- clearskies/configs/list_any_dict_or_callable.py +0 -31
- clearskies/configs/model_class.py +0 -35
- clearskies/configs/model_column.py +0 -65
- clearskies/configs/model_columns.py +0 -56
- clearskies/configs/model_destination_name.py +0 -25
- clearskies/configs/model_to_id_column.py +0 -43
- clearskies/configs/readable_model_column.py +0 -9
- clearskies/configs/readable_model_columns.py +0 -9
- clearskies/configs/schema.py +0 -23
- clearskies/configs/searchable_model_columns.py +0 -9
- clearskies/configs/security_headers.py +0 -39
- clearskies/configs/select.py +0 -26
- clearskies/configs/select_list.py +0 -47
- clearskies/configs/string.py +0 -29
- clearskies/configs/string_dict.py +0 -32
- clearskies/configs/string_list.py +0 -32
- clearskies/configs/string_list_or_callable.py +0 -35
- clearskies/configs/string_or_callable.py +0 -18
- clearskies/configs/timedelta.py +0 -18
- clearskies/configs/timezone.py +0 -18
- clearskies/configs/url.py +0 -23
- clearskies/configs/validators.py +0 -45
- clearskies/configs/writeable_model_column.py +0 -9
- clearskies/configs/writeable_model_columns.py +0 -9
- clearskies/configurable.py +0 -76
- clearskies/contexts/__init__.py +0 -11
- clearskies/contexts/cli.py +0 -117
- clearskies/contexts/context.py +0 -98
- clearskies/contexts/wsgi.py +0 -76
- clearskies/contexts/wsgi_ref.py +0 -82
- clearskies/decorators.py +0 -33
- clearskies/di/__init__.py +0 -14
- clearskies/di/additional_config.py +0 -130
- clearskies/di/additional_config_auto_import.py +0 -17
- clearskies/di/di.py +0 -968
- clearskies/di/inject/__init__.py +0 -23
- clearskies/di/inject/by_class.py +0 -21
- clearskies/di/inject/by_name.py +0 -18
- clearskies/di/inject/di.py +0 -13
- clearskies/di/inject/environment.py +0 -14
- clearskies/di/inject/input_output.py +0 -20
- clearskies/di/inject/now.py +0 -13
- clearskies/di/inject/requests.py +0 -13
- clearskies/di/inject/secrets.py +0 -14
- clearskies/di/inject/utcnow.py +0 -13
- clearskies/di/inject/uuid.py +0 -15
- clearskies/di/injectable.py +0 -29
- clearskies/di/injectable_properties.py +0 -131
- 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/end.py +0 -183
- clearskies/endpoint.py +0 -1310
- clearskies/endpoint_group.py +0 -310
- clearskies/endpoints/__init__.py +0 -23
- clearskies/endpoints/advanced_search.py +0 -526
- clearskies/endpoints/callable.py +0 -388
- clearskies/endpoints/create.py +0 -202
- clearskies/endpoints/delete.py +0 -139
- clearskies/endpoints/get.py +0 -275
- clearskies/endpoints/health_check.py +0 -181
- clearskies/endpoints/list.py +0 -573
- clearskies/endpoints/restful_api.py +0 -427
- clearskies/endpoints/simple_search.py +0 -286
- clearskies/endpoints/update.py +0 -190
- clearskies/environment.py +0 -104
- clearskies/exceptions/__init__.py +0 -17
- clearskies/exceptions/authentication.py +0 -2
- clearskies/exceptions/authorization.py +0 -2
- clearskies/exceptions/client_error.py +0 -2
- clearskies/exceptions/input_errors.py +0 -4
- clearskies/exceptions/moved_permanently.py +0 -3
- clearskies/exceptions/moved_temporarily.py +0 -3
- clearskies/exceptions/not_found.py +0 -2
- clearskies/functional/__init__.py +0 -7
- clearskies/functional/routing.py +0 -92
- clearskies/functional/string.py +0 -112
- clearskies/functional/validations.py +0 -76
- clearskies/input_outputs/__init__.py +0 -13
- clearskies/input_outputs/cli.py +0 -171
- clearskies/input_outputs/exceptions/__init__.py +0 -2
- clearskies/input_outputs/exceptions/cli_input_error.py +0 -2
- clearskies/input_outputs/exceptions/cli_not_found.py +0 -2
- clearskies/input_outputs/headers.py +0 -45
- clearskies/input_outputs/input_output.py +0 -138
- clearskies/input_outputs/programmatic.py +0 -69
- clearskies/input_outputs/py.typed +0 -0
- clearskies/input_outputs/wsgi.py +0 -77
- clearskies/model.py +0 -1922
- clearskies/py.typed +0 -0
- clearskies/query/__init__.py +0 -12
- clearskies/query/condition.py +0 -223
- clearskies/query/join.py +0 -136
- clearskies/query/query.py +0 -196
- clearskies/query/sort.py +0 -27
- clearskies/schema.py +0 -82
- clearskies/secrets/__init__.py +0 -6
- clearskies/secrets/additional_configs/__init__.py +0 -32
- clearskies/secrets/additional_configs/mysql_connection_dynamic_producer.py +0 -61
- clearskies/secrets/additional_configs/mysql_connection_dynamic_producer_via_ssh_cert_bastion.py +0 -160
- clearskies/secrets/akeyless.py +0 -182
- clearskies/secrets/exceptions/__init__.py +0 -1
- clearskies/secrets/exceptions/not_found.py +0 -2
- clearskies/secrets/secrets.py +0 -38
- clearskies/security_header.py +0 -15
- clearskies/security_headers/__init__.py +0 -11
- clearskies/security_headers/cache_control.py +0 -67
- clearskies/security_headers/cors.py +0 -50
- clearskies/security_headers/csp.py +0 -94
- clearskies/security_headers/hsts.py +0 -22
- clearskies/security_headers/x_content_type_options.py +0 -0
- clearskies/security_headers/x_frame_options.py +0 -0
- clearskies/test_base.py +0 -8
- clearskies/typing.py +0 -11
- clearskies/validator.py +0 -37
- clearskies/validators/__init__.py +0 -33
- clearskies/validators/after_column.py +0 -62
- clearskies/validators/before_column.py +0 -13
- clearskies/validators/in_the_future.py +0 -32
- clearskies/validators/in_the_future_at_least.py +0 -11
- clearskies/validators/in_the_future_at_most.py +0 -10
- clearskies/validators/in_the_past.py +0 -32
- clearskies/validators/in_the_past_at_least.py +0 -10
- clearskies/validators/in_the_past_at_most.py +0 -10
- clearskies/validators/maximum_length.py +0 -26
- clearskies/validators/maximum_value.py +0 -29
- clearskies/validators/minimum_length.py +0 -26
- clearskies/validators/minimum_value.py +0 -29
- clearskies/validators/required.py +0 -34
- clearskies/validators/timedelta.py +0 -59
- clearskies/validators/unique.py +0 -30
- {clear_skies-2.0.3.dist-info → clear_skies-2.0.5.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import clearskies.configs
|
|
2
|
-
import clearskies.decorators
|
|
3
|
-
from clearskies.security_header import SecurityHeader
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Csp(SecurityHeader):
|
|
7
|
-
header_name = "content-security-policy"
|
|
8
|
-
default_src = clearskies.configs.String()
|
|
9
|
-
script_src = clearskies.configs.String()
|
|
10
|
-
style_src = clearskies.configs.String()
|
|
11
|
-
img_src = clearskies.configs.String()
|
|
12
|
-
connect_src = clearskies.configs.String()
|
|
13
|
-
font_src = clearskies.configs.String()
|
|
14
|
-
object_src = clearskies.configs.String()
|
|
15
|
-
media_src = clearskies.configs.String()
|
|
16
|
-
frame_src = clearskies.configs.String()
|
|
17
|
-
sandbox = clearskies.configs.String()
|
|
18
|
-
report_uri = clearskies.configs.String()
|
|
19
|
-
child_src = clearskies.configs.String()
|
|
20
|
-
form_action = clearskies.configs.String()
|
|
21
|
-
frame_ancestors = clearskies.configs.String()
|
|
22
|
-
plugin_types = clearskies.configs.String()
|
|
23
|
-
base_uri = clearskies.configs.String()
|
|
24
|
-
report_to = clearskies.configs.String()
|
|
25
|
-
worker_src = clearskies.configs.String()
|
|
26
|
-
manifest_src = clearskies.configs.String()
|
|
27
|
-
prefetch_src = clearskies.configs.String()
|
|
28
|
-
navigate_to = clearskies.configs.String()
|
|
29
|
-
|
|
30
|
-
directives = [
|
|
31
|
-
"default_src",
|
|
32
|
-
"script_src",
|
|
33
|
-
"style_src",
|
|
34
|
-
"img_src",
|
|
35
|
-
"connect_src",
|
|
36
|
-
"font_src",
|
|
37
|
-
"object_src",
|
|
38
|
-
"media_src",
|
|
39
|
-
"frame_src",
|
|
40
|
-
"sandbox",
|
|
41
|
-
"report_uri",
|
|
42
|
-
"child_src",
|
|
43
|
-
"form_action",
|
|
44
|
-
"frame_ancestors",
|
|
45
|
-
"plugin_types",
|
|
46
|
-
"base_uri",
|
|
47
|
-
"report_to",
|
|
48
|
-
"worker_src",
|
|
49
|
-
"manifest_src",
|
|
50
|
-
"prefetch_src",
|
|
51
|
-
"navigate_to",
|
|
52
|
-
]
|
|
53
|
-
|
|
54
|
-
@clearskies.decorators.parameters_to_properties
|
|
55
|
-
def __init__(
|
|
56
|
-
self,
|
|
57
|
-
default_src: str = "",
|
|
58
|
-
script_src: str = "",
|
|
59
|
-
style_src: str = "",
|
|
60
|
-
img_src: str = "",
|
|
61
|
-
connect_src: str = "",
|
|
62
|
-
font_src: str = "",
|
|
63
|
-
object_src: str = "",
|
|
64
|
-
media_src: str = "",
|
|
65
|
-
frame_src: str = "",
|
|
66
|
-
sandbox: str = "",
|
|
67
|
-
report_uri: str = "",
|
|
68
|
-
child_src: str = "",
|
|
69
|
-
form_action: str = "",
|
|
70
|
-
frame_ancestors: str = "",
|
|
71
|
-
plugin_types: str = "",
|
|
72
|
-
base_uri: str = "",
|
|
73
|
-
report_to: str = "",
|
|
74
|
-
worker_src: str = "",
|
|
75
|
-
manifest_src: str = "",
|
|
76
|
-
prefetch_src: str = "",
|
|
77
|
-
navigate_to: str = "",
|
|
78
|
-
):
|
|
79
|
-
self.finalize_and_validate_configuration()
|
|
80
|
-
|
|
81
|
-
def set_headers_for_input_output(self, input_output):
|
|
82
|
-
parts = []
|
|
83
|
-
for variable_name in self.directives:
|
|
84
|
-
value = getattr(self, variable_name)
|
|
85
|
-
if not value:
|
|
86
|
-
continue
|
|
87
|
-
if value.lower().strip() == "self":
|
|
88
|
-
value = "'self'"
|
|
89
|
-
header_key_name = variable_name.replace("_", "-")
|
|
90
|
-
parts.append(f"{header_key_name} {value}")
|
|
91
|
-
if not parts:
|
|
92
|
-
return
|
|
93
|
-
header_value = "; ".join(parts)
|
|
94
|
-
input_output.response_headers.add(self.header_name, header_value)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import clearskies.configs
|
|
2
|
-
import clearskies.decorators
|
|
3
|
-
from clearskies.security_header import SecurityHeader
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class Hsts(SecurityHeader):
|
|
7
|
-
max_age = clearskies.configs.Integer(default=31536000)
|
|
8
|
-
include_sub_domains = clearskies.configs.Boolean()
|
|
9
|
-
|
|
10
|
-
@clearskies.decorators.parameters_to_properties
|
|
11
|
-
def __init__(
|
|
12
|
-
self,
|
|
13
|
-
max_age: int = 31536000,
|
|
14
|
-
include_sub_domains: bool = False,
|
|
15
|
-
):
|
|
16
|
-
self.finalize_and_validate_configuration()
|
|
17
|
-
|
|
18
|
-
def set_headers_for_input_output(self, input_output):
|
|
19
|
-
value = f"max-age={self.max_age} ;"
|
|
20
|
-
if self.include_sub_domains:
|
|
21
|
-
value += " includeSubDomains"
|
|
22
|
-
input_output.response_headers.add("strict-transport-security", value)
|
|
File without changes
|
|
File without changes
|
clearskies/test_base.py
DELETED
clearskies/typing.py
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
from typing import Any, Callable
|
|
2
|
-
|
|
3
|
-
from clearskies.action import Action
|
|
4
|
-
from clearskies.query.condition import Condition
|
|
5
|
-
from clearskies.validator import Validator
|
|
6
|
-
|
|
7
|
-
action = Callable[..., dict[str, Any]] | Action
|
|
8
|
-
condition = str | Callable | Condition
|
|
9
|
-
join = str | Callable[..., str]
|
|
10
|
-
validator = Callable[..., str] | Validator
|
|
11
|
-
response = str | bytes | dict[str, Any] | list[Any]
|
clearskies/validator.py
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
from clearskies import configurable
|
|
7
|
-
|
|
8
|
-
if TYPE_CHECKING:
|
|
9
|
-
import clearskies.column
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Validator(ABC, configurable.Configurable):
|
|
14
|
-
"""
|
|
15
|
-
Attach input validation rules to columns!
|
|
16
|
-
|
|
17
|
-
The validators provide a way to attach input validation logic to columns. The columns themselves already
|
|
18
|
-
provide basic validation (making sure strings are strings, integers are integers, etc...) but these classes
|
|
19
|
-
allow for more detailed rules.
|
|
20
|
-
|
|
21
|
-
It's important to understand that validators only apply to client input, which means that input validation
|
|
22
|
-
is only enforced by appropriate endpoints. If you inject a model into a function of your own and execute
|
|
23
|
-
a save operation with it, validators will **NOT** be checked.
|
|
24
|
-
"""
|
|
25
|
-
|
|
26
|
-
is_unique = False
|
|
27
|
-
is_required = False
|
|
28
|
-
|
|
29
|
-
def __call__(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
30
|
-
return self.check(model, column_name, data)
|
|
31
|
-
|
|
32
|
-
@abstractmethod
|
|
33
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
34
|
-
pass
|
|
35
|
-
|
|
36
|
-
def additional_write_columns(self, is_create=False) -> dict[str, clearskies.column.Column]:
|
|
37
|
-
return {}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
from clearskies.validators.after_column import AfterColumn
|
|
2
|
-
from clearskies.validators.before_column import BeforeColumn
|
|
3
|
-
from clearskies.validators.in_the_future import InTheFuture
|
|
4
|
-
from clearskies.validators.in_the_future_at_least import InTheFutureAtLeast
|
|
5
|
-
from clearskies.validators.in_the_future_at_most import InTheFutureAtMost
|
|
6
|
-
from clearskies.validators.in_the_past import InThePast
|
|
7
|
-
from clearskies.validators.in_the_past_at_least import InThePastAtLeast
|
|
8
|
-
from clearskies.validators.in_the_past_at_most import InThePastAtMost
|
|
9
|
-
from clearskies.validators.maximum_length import MaximumLength
|
|
10
|
-
from clearskies.validators.maximum_value import MaximumValue
|
|
11
|
-
from clearskies.validators.minimum_length import MinimumLength
|
|
12
|
-
from clearskies.validators.minimum_value import MinimumValue
|
|
13
|
-
from clearskies.validators.required import Required
|
|
14
|
-
from clearskies.validators.timedelta import Timedelta
|
|
15
|
-
from clearskies.validators.unique import Unique
|
|
16
|
-
|
|
17
|
-
__all__ = [
|
|
18
|
-
"AfterColumn",
|
|
19
|
-
"BeforeColumn",
|
|
20
|
-
"InTheFuture",
|
|
21
|
-
"InTheFutureAtLeast",
|
|
22
|
-
"InTheFutureAtMost",
|
|
23
|
-
"InThePast",
|
|
24
|
-
"InThePastAtLeast",
|
|
25
|
-
"InThePastAtMost",
|
|
26
|
-
"MaximumLength",
|
|
27
|
-
"MaximumValue",
|
|
28
|
-
"MinimumLength",
|
|
29
|
-
"MaximumLength",
|
|
30
|
-
"Required",
|
|
31
|
-
"Timedelta",
|
|
32
|
-
"Unique",
|
|
33
|
-
]
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import dateparser
|
|
7
|
-
|
|
8
|
-
import clearskies.configs
|
|
9
|
-
import clearskies.decorators
|
|
10
|
-
from clearskies.validator import Validator
|
|
11
|
-
|
|
12
|
-
if TYPE_CHECKING:
|
|
13
|
-
import clearskies.model
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class AfterColumn(Validator):
|
|
17
|
-
"""The name of the other date column for comparison."""
|
|
18
|
-
|
|
19
|
-
other_column_name = clearskies.configs.String(default="", required=True)
|
|
20
|
-
|
|
21
|
-
"""
|
|
22
|
-
If true, then this column is allowed to be eqaul to the other column.
|
|
23
|
-
"""
|
|
24
|
-
allow_equal = clearskies.configs.Boolean(default=False)
|
|
25
|
-
|
|
26
|
-
@clearskies.decorators.parameters_to_properties
|
|
27
|
-
def __init__(self, other_column_name: str, allow_equal: bool = False):
|
|
28
|
-
self.other_column_name = other_column_name
|
|
29
|
-
self.allow_equal = allow_equal
|
|
30
|
-
self.finalize_and_validate_configuration()
|
|
31
|
-
|
|
32
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
33
|
-
# we won't check anything for missing values (columns should be required if that is an issue)
|
|
34
|
-
if not data.get(column_name):
|
|
35
|
-
return ""
|
|
36
|
-
my_value = data[column_name]
|
|
37
|
-
other_value = data.get(self.other_column_name, getattr(model, self.other_column_name))
|
|
38
|
-
# again, no checks for non-values
|
|
39
|
-
if not other_value:
|
|
40
|
-
return ""
|
|
41
|
-
|
|
42
|
-
my_value = dateparser.parse(my_value) if isinstance(my_value, str) else my_value
|
|
43
|
-
if not my_value:
|
|
44
|
-
return f"'{column_name}' was not a valid date."
|
|
45
|
-
|
|
46
|
-
if type(other_value) != str and type(other_value) != datetime.datetime:
|
|
47
|
-
return f"'{self.other_column_name}' was not a valid date."
|
|
48
|
-
other_value = dateparser.parse(other_value) if isinstance(other_value, str) else other_value
|
|
49
|
-
if not other_value:
|
|
50
|
-
return f"'{self.other_column_name}' was not a valid date."
|
|
51
|
-
|
|
52
|
-
return self.date_comparison(my_value, other_value, column_name)
|
|
53
|
-
|
|
54
|
-
def date_comparison(
|
|
55
|
-
self, incoming_date: datetime.datetime, comparison_date: datetime.datetime, column_name: str
|
|
56
|
-
) -> str:
|
|
57
|
-
if incoming_date == comparison_date:
|
|
58
|
-
return "" if self.allow_equal else f"'{column_name}' must be after '{self.other_column_name}'"
|
|
59
|
-
|
|
60
|
-
if incoming_date < comparison_date:
|
|
61
|
-
return f"'{column_name}' must be after '{self.other_column_name}'"
|
|
62
|
-
return ""
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
from clearskies.validators.after_column import AfterColumn
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class BeforeColumn(AfterColumn):
|
|
7
|
-
def date_comparison(self, incoming_date: datetime.datetime, comparison_date: datetime.datetime, column_name) -> str:
|
|
8
|
-
if incoming_date == comparison_date:
|
|
9
|
-
return "" if self.allow_equal else f"'{column_name}' must be before '{self.other_column_name}'"
|
|
10
|
-
|
|
11
|
-
if incoming_date > comparison_date:
|
|
12
|
-
return f"'{column_name}' must be before '{self.other_column_name}'"
|
|
13
|
-
return ""
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from collections import OrderedDict
|
|
5
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
-
|
|
7
|
-
import dateparser
|
|
8
|
-
|
|
9
|
-
import clearskies.configs
|
|
10
|
-
import clearskies.decorators
|
|
11
|
-
import clearskies.di
|
|
12
|
-
from clearskies.validator import Validator
|
|
13
|
-
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
import clearskies.model
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class InTheFuture(Validator, clearskies.di.InjectableProperties):
|
|
19
|
-
utcnow = clearskies.di.inject.Utcnow()
|
|
20
|
-
|
|
21
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
22
|
-
if not data.get(column_name):
|
|
23
|
-
return ""
|
|
24
|
-
|
|
25
|
-
as_date = dateparser.parse(data[column_name]) if isinstance(data[column_name], str) else data[column_name]
|
|
26
|
-
if not as_date:
|
|
27
|
-
return f"'{column_name}' was not a valid date"
|
|
28
|
-
if as_date.tzinfo == None:
|
|
29
|
-
as_date = as_date.replace(tzinfo=datetime.timezone.utc)
|
|
30
|
-
if as_date <= self.utcnow:
|
|
31
|
-
return f"'{column_name}' must be in the future"
|
|
32
|
-
return ""
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
from clearskies.validators.timedelta import Timedelta
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class InTheFutureAtLeast(Timedelta):
|
|
7
|
-
def check_timedelta(self, as_date: datetime.datetime, column_name: str) -> str:
|
|
8
|
-
if as_date < self.utcnow + self.timedelta:
|
|
9
|
-
human_friendly = self.delta_human_friendly()
|
|
10
|
-
return f"'{column_name}' must be at least {human_friendly} in the future."
|
|
11
|
-
return ""
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
from clearskies.validators.timedelta import Timedelta
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class InTheFutureAtMost(Timedelta):
|
|
7
|
-
def check_timedelta(self, as_date: datetime.datetime, column_name: str) -> str:
|
|
8
|
-
if as_date > self.utcnow + self.timedelta:
|
|
9
|
-
return f"'{column_name}' must be at most {self.delta_human_friendly()} in the future."
|
|
10
|
-
return ""
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from collections import OrderedDict
|
|
5
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
-
|
|
7
|
-
import dateparser
|
|
8
|
-
|
|
9
|
-
import clearskies.configs
|
|
10
|
-
import clearskies.decorators
|
|
11
|
-
import clearskies.di
|
|
12
|
-
from clearskies.validator import Validator
|
|
13
|
-
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
import clearskies.model
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class InThePast(Validator, clearskies.di.InjectableProperties):
|
|
19
|
-
utcnow = clearskies.di.inject.Utcnow()
|
|
20
|
-
|
|
21
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
22
|
-
if not data.get(column_name):
|
|
23
|
-
return ""
|
|
24
|
-
|
|
25
|
-
as_date = dateparser.parse(data[column_name]) if isinstance(data[column_name], str) else data[column_name]
|
|
26
|
-
if not as_date:
|
|
27
|
-
return f"'{column_name}' was not a valid date"
|
|
28
|
-
if as_date.tzinfo == None:
|
|
29
|
-
as_date = as_date.replace(tzinfo=datetime.timezone.utc)
|
|
30
|
-
if as_date >= self.utcnow:
|
|
31
|
-
return f"'{column_name}' must be in the past"
|
|
32
|
-
return ""
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
from clearskies.validators.timedelta import Timedelta
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class InThePastAtLeast(Timedelta):
|
|
7
|
-
def check_timedelta(self, as_date: datetime.datetime, column_name: str) -> str:
|
|
8
|
-
if as_date > self.utcnow - self.timedelta:
|
|
9
|
-
return f"'{column_name}' must be at least {self.delta_human_friendly()} in the past."
|
|
10
|
-
return ""
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import datetime
|
|
2
|
-
|
|
3
|
-
from clearskies.validators.timedelta import Timedelta
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
class InThePastAtMost(Timedelta):
|
|
7
|
-
def check_timedelta(self, as_date: datetime.datetime, column_name: str) -> str:
|
|
8
|
-
if as_date < self.utcnow - self.timedelta:
|
|
9
|
-
return f"'{column_name}' must be at most {self.delta_human_friendly()} in the past."
|
|
10
|
-
return ""
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.configs
|
|
7
|
-
from clearskies.validator import Validator
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class MaximumLength(Validator):
|
|
14
|
-
maximum_length = clearskies.configs.Integer(required=True)
|
|
15
|
-
|
|
16
|
-
def __init__(self, maximum_length: int):
|
|
17
|
-
self.maximum_length = maximum_length
|
|
18
|
-
self.finalize_and_validate_configuration()
|
|
19
|
-
|
|
20
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
|
-
# we won't check anything for missing values (columns should be required if that is an issue)
|
|
22
|
-
if not data.get(column_name):
|
|
23
|
-
return ""
|
|
24
|
-
if len(data[column_name]) <= self.maximum_length:
|
|
25
|
-
return ""
|
|
26
|
-
return f"'{column_name}' must be at most {self.maximum_length} characters long."
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.configs
|
|
7
|
-
from clearskies.validator import Validator
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class MaximumValue(Validator):
|
|
14
|
-
maximum_value = clearskies.configs.Integer(required=True)
|
|
15
|
-
|
|
16
|
-
def __init__(self, maximum_value: int):
|
|
17
|
-
self.maximum_value = maximum_value
|
|
18
|
-
self.finalize_and_validate_configuration()
|
|
19
|
-
|
|
20
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
|
-
if column_name not in data:
|
|
22
|
-
return ""
|
|
23
|
-
try:
|
|
24
|
-
value = float(data[column_name])
|
|
25
|
-
except ValueError:
|
|
26
|
-
return f"{column_name} must be an integer or float"
|
|
27
|
-
if float(value) <= self.maximum_value:
|
|
28
|
-
return ""
|
|
29
|
-
return f"'{column_name}' must be at most {self.maximum_value}."
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.configs
|
|
7
|
-
from clearskies.validator import Validator
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class MinimumLength(Validator):
|
|
14
|
-
minimum_length = clearskies.configs.Integer(required=True)
|
|
15
|
-
|
|
16
|
-
def __init__(self, minimum_length: int):
|
|
17
|
-
self.minimum_length = minimum_length
|
|
18
|
-
self.finalize_and_validate_configuration()
|
|
19
|
-
|
|
20
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
|
-
# we won't check anything for missing values (columns should be required if that is an issue)
|
|
22
|
-
if not data.get(column_name):
|
|
23
|
-
return ""
|
|
24
|
-
if len(data[column_name]) >= self.minimum_length:
|
|
25
|
-
return ""
|
|
26
|
-
return f"'{column_name}' must be at least {self.minimum_length} characters long."
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.configs
|
|
7
|
-
from clearskies.validator import Validator
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class MinimumValue(Validator):
|
|
14
|
-
minimum_value = clearskies.configs.Integer(required=True)
|
|
15
|
-
|
|
16
|
-
def __init__(self, minimum_value: int):
|
|
17
|
-
self.minimum_value = minimum_value
|
|
18
|
-
self.finalize_and_validate_configuration()
|
|
19
|
-
|
|
20
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
|
-
if column_name not in data:
|
|
22
|
-
return ""
|
|
23
|
-
try:
|
|
24
|
-
value = float(data[column_name])
|
|
25
|
-
except ValueError:
|
|
26
|
-
return f"{column_name} must be an integer or float"
|
|
27
|
-
if float(value) >= self.minimum_value:
|
|
28
|
-
return ""
|
|
29
|
-
return f"'{column_name}' must be at least {self.minimum_value}."
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.configs
|
|
7
|
-
from clearskies.validator import Validator
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Required(Validator):
|
|
14
|
-
is_required = True
|
|
15
|
-
|
|
16
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
17
|
-
# you'd think that "required" is straight forward and we want an input error if it isn't found.
|
|
18
|
-
# this isn't strictly true though. If the model already exists, the column has a value in the model already,
|
|
19
|
-
# and the column is completely missing from the input data, then it is actually perfectly fine (because
|
|
20
|
-
# there will still be a value in the column after the save). However, if the model doesn't exist, then
|
|
21
|
-
# we must require the column in the data with an actual value.
|
|
22
|
-
has_value = False
|
|
23
|
-
has_some_value = False
|
|
24
|
-
if column_name in data:
|
|
25
|
-
has_some_value = True
|
|
26
|
-
if type(data[column_name]) == str:
|
|
27
|
-
has_value = bool(data[column_name].strip())
|
|
28
|
-
else:
|
|
29
|
-
has_value = bool(data[column_name])
|
|
30
|
-
if has_value:
|
|
31
|
-
return ""
|
|
32
|
-
if model and getattr(model, column_name) and not has_some_value:
|
|
33
|
-
return ""
|
|
34
|
-
return f"'{column_name}' is required."
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from collections import OrderedDict
|
|
5
|
-
from typing import TYPE_CHECKING, Any
|
|
6
|
-
|
|
7
|
-
import dateparser
|
|
8
|
-
|
|
9
|
-
import clearskies.configs
|
|
10
|
-
import clearskies.decorators
|
|
11
|
-
import clearskies.di
|
|
12
|
-
from clearskies.validator import Validator
|
|
13
|
-
|
|
14
|
-
if TYPE_CHECKING:
|
|
15
|
-
import clearskies.model
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class Timedelta(Validator, clearskies.di.InjectableProperties):
|
|
19
|
-
timedelta = clearskies.configs.Timedelta(default=None)
|
|
20
|
-
|
|
21
|
-
utcnow = clearskies.di.inject.Utcnow()
|
|
22
|
-
|
|
23
|
-
@clearskies.decorators.parameters_to_properties
|
|
24
|
-
def __init__(self, timedelta: datetime.timedelta):
|
|
25
|
-
self.finalize_and_validate_configuration()
|
|
26
|
-
|
|
27
|
-
def delta_human_friendly(self):
|
|
28
|
-
remainder = int(self.timedelta.total_seconds())
|
|
29
|
-
parts = []
|
|
30
|
-
conversion = OrderedDict(
|
|
31
|
-
[
|
|
32
|
-
("year", 31536000),
|
|
33
|
-
("day", 86400),
|
|
34
|
-
("hour", 3600),
|
|
35
|
-
("minute", 60),
|
|
36
|
-
("second", 1),
|
|
37
|
-
]
|
|
38
|
-
)
|
|
39
|
-
for name, num_seconds in conversion.items():
|
|
40
|
-
if num_seconds > remainder:
|
|
41
|
-
continue
|
|
42
|
-
amount = int(remainder / num_seconds)
|
|
43
|
-
remainder -= amount * num_seconds
|
|
44
|
-
parts.append(f"{amount} {name}" + ("s" if amount != 1 else ""))
|
|
45
|
-
return ", ".join(parts)
|
|
46
|
-
|
|
47
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
48
|
-
if not data.get(column_name):
|
|
49
|
-
return ""
|
|
50
|
-
|
|
51
|
-
as_date = dateparser.parse(data[column_name]) if isinstance(data[column_name], str) else data[column_name]
|
|
52
|
-
if not as_date:
|
|
53
|
-
return f"'{column_name}' was not a valid date"
|
|
54
|
-
if as_date.tzinfo == None:
|
|
55
|
-
as_date = as_date.replace(tzinfo=datetime.timezone.utc)
|
|
56
|
-
return self.check_timedelta(as_date, column_name)
|
|
57
|
-
|
|
58
|
-
def check_timedelta(self, as_date: datetime.datetime, column_name: str) -> str:
|
|
59
|
-
return ""
|
clearskies/validators/unique.py
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import datetime
|
|
4
|
-
from typing import TYPE_CHECKING, Any
|
|
5
|
-
|
|
6
|
-
import clearskies.configs
|
|
7
|
-
from clearskies.validator import Validator
|
|
8
|
-
|
|
9
|
-
if TYPE_CHECKING:
|
|
10
|
-
import clearskies.model
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class Unique(Validator):
|
|
14
|
-
is_unique = True
|
|
15
|
-
|
|
16
|
-
def check(self, model: clearskies.model.Model, column_name: str, data: dict[str, Any]) -> str:
|
|
17
|
-
# Unique is mildly tricky. We obviously want to search the backend for the new value,
|
|
18
|
-
# but we need to first skip this if our column is not being set, or if we're editing
|
|
19
|
-
# the model and nothing is changing.
|
|
20
|
-
if column_name not in data:
|
|
21
|
-
return ""
|
|
22
|
-
new_value = data[column_name]
|
|
23
|
-
if model and getattr(model, column_name) == new_value:
|
|
24
|
-
return ""
|
|
25
|
-
|
|
26
|
-
as_query = model.as_query()
|
|
27
|
-
matching_model = as_query.find(f"{column_name}={new_value}")
|
|
28
|
-
if matching_model:
|
|
29
|
-
return f"Invalid value for '{column_name}': the given value already exists, and must be unique."
|
|
30
|
-
return ""
|
|
File without changes
|