clear-skies 2.0.7__py3-none-any.whl → 2.0.9__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.7.dist-info → clear_skies-2.0.9.dist-info}/METADATA +1 -1
- clear_skies-2.0.9.dist-info/RECORD +256 -0
- clearskies/__init__.py +2 -2
- clearskies/authentication/authentication.py +1 -3
- clearskies/authentication/authorization.py +12 -5
- clearskies/authentication/authorization_pass_through.py +5 -3
- clearskies/authentication/jwks.py +25 -23
- clearskies/authentication/secret_bearer.py +15 -17
- clearskies/autodoc/schema/schema.py +1 -1
- clearskies/backends/api_backend.py +50 -56
- clearskies/backends/backend.py +14 -14
- clearskies/backends/cursor_backend.py +17 -23
- clearskies/backends/memory_backend.py +27 -30
- clearskies/backends/secrets_backend.py +13 -18
- clearskies/column.py +44 -56
- clearskies/columns/audit.py +14 -13
- clearskies/columns/belongs_to_id.py +10 -15
- clearskies/columns/belongs_to_model.py +6 -9
- clearskies/columns/belongs_to_self.py +13 -9
- clearskies/columns/boolean.py +13 -16
- clearskies/columns/category_tree.py +9 -11
- clearskies/columns/category_tree_children.py +2 -3
- clearskies/columns/category_tree_descendants.py +1 -1
- clearskies/columns/created.py +8 -11
- clearskies/columns/created_by_authorization_data.py +7 -9
- clearskies/columns/created_by_header.py +12 -8
- clearskies/columns/created_by_ip.py +6 -8
- clearskies/columns/created_by_routing_data.py +12 -7
- clearskies/columns/created_by_user_agent.py +6 -9
- clearskies/columns/date.py +12 -14
- clearskies/columns/datetime.py +19 -17
- clearskies/columns/email.py +3 -1
- clearskies/columns/float.py +10 -14
- clearskies/columns/has_many.py +8 -10
- clearskies/columns/has_many_self.py +13 -7
- clearskies/columns/has_one.py +2 -0
- clearskies/columns/integer.py +9 -11
- clearskies/columns/json.py +10 -12
- clearskies/columns/many_to_many_ids.py +14 -16
- clearskies/columns/many_to_many_ids_with_data.py +16 -16
- clearskies/columns/many_to_many_models.py +5 -7
- clearskies/columns/many_to_many_pivots.py +3 -5
- clearskies/columns/phone.py +12 -9
- clearskies/columns/select.py +12 -9
- clearskies/columns/string.py +1 -1
- clearskies/columns/timestamp.py +15 -15
- clearskies/columns/updated.py +8 -10
- clearskies/columns/uuid.py +7 -10
- clearskies/configs/__init__.py +8 -0
- clearskies/configs/any.py +2 -0
- clearskies/configs/any_dict.py +2 -0
- clearskies/configs/any_dict_or_callable.py +2 -0
- clearskies/configs/boolean.py +2 -0
- clearskies/configs/boolean_or_callable.py +2 -0
- clearskies/configs/callable_config.py +2 -0
- clearskies/configs/config.py +2 -0
- clearskies/configs/datetime.py +2 -0
- clearskies/configs/datetime_or_callable.py +2 -0
- clearskies/configs/email.py +10 -0
- clearskies/configs/email_list.py +17 -0
- clearskies/configs/email_list_or_callable.py +19 -0
- clearskies/configs/email_or_email_list_or_callable.py +59 -0
- clearskies/configs/float.py +2 -0
- clearskies/configs/float_or_callable.py +2 -0
- clearskies/configs/integer.py +2 -0
- clearskies/configs/integer_or_callable.py +2 -0
- clearskies/configs/list_any_dict.py +2 -0
- clearskies/configs/list_any_dict_or_callable.py +2 -0
- clearskies/configs/model_column.py +2 -0
- clearskies/configs/model_columns.py +2 -0
- clearskies/configs/model_destination_name.py +2 -1
- clearskies/configs/model_to_id_column.py +2 -0
- clearskies/configs/readable_model_column.py +2 -0
- clearskies/configs/readable_model_columns.py +2 -0
- clearskies/configs/searchable_model_columns.py +2 -0
- clearskies/configs/select.py +2 -0
- clearskies/configs/select_list.py +2 -0
- clearskies/configs/string.py +4 -2
- clearskies/configs/string_dict.py +2 -0
- clearskies/configs/string_list.py +17 -2
- clearskies/configs/string_list_or_callable.py +13 -0
- clearskies/configs/timedelta.py +2 -0
- clearskies/configs/timezone.py +2 -0
- clearskies/configs/url.py +2 -0
- clearskies/configs/writeable_model_column.py +2 -0
- clearskies/configs/writeable_model_columns.py +2 -0
- clearskies/configurable.py +2 -0
- clearskies/contexts/cli.py +9 -1
- clearskies/contexts/context.py +13 -14
- clearskies/contexts/wsgi.py +12 -10
- clearskies/contexts/wsgi_ref.py +12 -6
- clearskies/decorators.py +1 -1
- clearskies/decorators.pyi +10 -0
- clearskies/di/di.py +7 -6
- clearskies/di/inject/by_class.py +2 -0
- clearskies/di/inject/by_name.py +2 -0
- clearskies/di/inject/di.py +2 -0
- clearskies/di/inject/environment.py +1 -1
- clearskies/di/inject/now.py +2 -0
- clearskies/di/inject/requests.py +2 -0
- clearskies/di/inject/secrets.py +2 -2
- clearskies/di/inject/utcnow.py +2 -0
- clearskies/di/inject/uuid.py +2 -2
- clearskies/end.py +45 -7
- clearskies/endpoint.py +43 -59
- clearskies/endpoint_group.py +15 -18
- clearskies/endpoints/advanced_search.py +19 -26
- clearskies/endpoints/callable.py +10 -16
- clearskies/endpoints/create.py +6 -10
- clearskies/endpoints/delete.py +5 -11
- clearskies/endpoints/get.py +11 -15
- clearskies/endpoints/health_check.py +9 -11
- clearskies/endpoints/list.py +29 -36
- clearskies/endpoints/restful_api.py +43 -53
- clearskies/endpoints/schema.py +14 -18
- clearskies/endpoints/simple_search.py +5 -12
- clearskies/endpoints/update.py +6 -11
- clearskies/environment.py +2 -0
- clearskies/input_outputs/cli.py +2 -0
- clearskies/input_outputs/headers.py +2 -0
- clearskies/input_outputs/input_output.py +15 -15
- clearskies/input_outputs/programmatic.py +2 -2
- clearskies/input_outputs/wsgi.py +2 -2
- clearskies/model.py +120 -25
- clearskies/query/query.py +1 -4
- clearskies/secrets/__init__.py +2 -1
- clearskies/secrets/akeyless.py +16 -11
- clearskies/secrets/secrets.py +7 -2
- clearskies/security_header.py +4 -2
- clearskies/security_headers/cache_control.py +15 -14
- clearskies/security_headers/cors.py +10 -9
- clearskies/security_headers/csp.py +25 -24
- clearskies/security_headers/hsts.py +6 -5
- clearskies/typing.py +1 -1
- clearskies/validator.py +5 -6
- clearskies/validators/after_column.py +6 -7
- clearskies/validators/before_column.py +2 -0
- clearskies/validators/in_the_future.py +5 -8
- clearskies/validators/in_the_future_at_least.py +2 -0
- clearskies/validators/in_the_future_at_most.py +2 -0
- clearskies/validators/in_the_past.py +5 -8
- clearskies/validators/in_the_past_at_least.py +2 -0
- clearskies/validators/in_the_past_at_most.py +2 -0
- clearskies/validators/maximum_length.py +4 -5
- clearskies/validators/maximum_value.py +4 -4
- clearskies/validators/minimum_length.py +4 -4
- clearskies/validators/minimum_value.py +4 -4
- clearskies/validators/required.py +2 -4
- clearskies/validators/timedelta.py +8 -9
- clearskies/validators/unique.py +2 -3
- clear_skies-2.0.7.dist-info/RECORD +0 -251
- {clear_skies-2.0.7.dist-info → clear_skies-2.0.9.dist-info}/WHEEL +0 -0
- {clear_skies-2.0.7.dist-info → clear_skies-2.0.9.dist-info}/licenses/LICENSE +0 -0
clearskies/query/query.py
CHANGED
|
@@ -2,12 +2,9 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
from typing import TYPE_CHECKING, Any, Self
|
|
4
4
|
|
|
5
|
-
from .condition import Condition
|
|
6
|
-
from .join import Join
|
|
7
|
-
from .sort import Sort
|
|
8
|
-
|
|
9
5
|
if TYPE_CHECKING:
|
|
10
6
|
from clearskies import Model
|
|
7
|
+
from clearskies.query import Condition, Join, Sort
|
|
11
8
|
|
|
12
9
|
|
|
13
10
|
class Query:
|
clearskies/secrets/__init__.py
CHANGED
clearskies/secrets/akeyless.py
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import datetime
|
|
2
4
|
from typing import Any
|
|
3
5
|
|
|
4
|
-
import
|
|
5
|
-
from clearskies.di import
|
|
6
|
+
from clearskies import configs, secrets
|
|
7
|
+
from clearskies.di import inject
|
|
6
8
|
|
|
7
9
|
|
|
8
|
-
class Akeyless(
|
|
9
|
-
requests =
|
|
10
|
-
environment =
|
|
11
|
-
akeyless =
|
|
10
|
+
class Akeyless(secrets.Secrets):
|
|
11
|
+
requests = inject.Requests()
|
|
12
|
+
environment = inject.Environment()
|
|
13
|
+
akeyless = inject.ByName("akeyless_sdk")
|
|
12
14
|
|
|
13
|
-
access_id =
|
|
14
|
-
access_type =
|
|
15
|
-
api_host =
|
|
16
|
-
profile =
|
|
15
|
+
access_id = configs.String(required=True, regexp=r"^p-[\d\w]+$")
|
|
16
|
+
access_type = configs.Select(["aws_iam", "saml", "jwt"], required=True)
|
|
17
|
+
api_host = configs.String(default="https://api.akeyless.io")
|
|
18
|
+
profile = configs.String(regexp=r"^[\d\w\-]+$")
|
|
17
19
|
|
|
18
20
|
_token_refresh: datetime.datetime = None # type: ignore
|
|
19
21
|
_token: str = ""
|
|
@@ -136,6 +138,7 @@ class Akeyless(clearskies.Configurable, clearskies.di.InjectableProperties):
|
|
|
136
138
|
return res.token
|
|
137
139
|
|
|
138
140
|
def auth_saml(self):
|
|
141
|
+
import json
|
|
139
142
|
import os
|
|
140
143
|
from pathlib import Path
|
|
141
144
|
|
|
@@ -143,7 +146,9 @@ class Akeyless(clearskies.Configurable, clearskies.di.InjectableProperties):
|
|
|
143
146
|
home = str(Path.home())
|
|
144
147
|
with open(f"{home}/.akeyless/.tmp_creds/{self.profile}-{self.access_id}", "r") as creds_file:
|
|
145
148
|
credentials = creds_file.read()
|
|
146
|
-
|
|
149
|
+
credentials_json = json.loads(credentials)
|
|
150
|
+
if "token" in credentials_json:
|
|
151
|
+
return credentials_json["token"]
|
|
147
152
|
# and now we can turn that into a token
|
|
148
153
|
response = self.requests.post(
|
|
149
154
|
"https://rest.akeyless.io/",
|
clearskies/secrets/secrets.py
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
1
4
|
from typing import Any
|
|
2
5
|
|
|
6
|
+
import clearskies.configurable
|
|
7
|
+
|
|
3
8
|
|
|
4
|
-
class Secrets:
|
|
5
|
-
def create(self, path: str, value: str) ->
|
|
9
|
+
class Secrets(ABC, clearskies.configurable.Configurable):
|
|
10
|
+
def create(self, path: str, value: str) -> bool:
|
|
6
11
|
raise NotImplementedError(
|
|
7
12
|
"It looks like you tried to use the secret system in clearskies, but didn't specify a secret manager."
|
|
8
13
|
)
|
clearskies/security_header.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from
|
|
1
|
+
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
from clearskies import configurable
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
|
|
6
|
+
class SecurityHeader(configurable.Configurable):
|
|
5
7
|
"""
|
|
6
8
|
Attach all the various security headers to endpoints.
|
|
7
9
|
|
|
@@ -1,20 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from clearskies import configs, decorators
|
|
3
4
|
from clearskies.security_header import SecurityHeader
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class CacheControl(SecurityHeader):
|
|
7
|
-
max_age =
|
|
8
|
-
s_maxage =
|
|
9
|
-
stale_while_revalidate =
|
|
10
|
-
stale_if_error =
|
|
11
|
-
immutable =
|
|
12
|
-
must_understand =
|
|
13
|
-
no_cache =
|
|
14
|
-
no_store =
|
|
15
|
-
no_transform =
|
|
16
|
-
private =
|
|
17
|
-
public =
|
|
8
|
+
max_age = configs.Integer()
|
|
9
|
+
s_maxage = configs.Integer()
|
|
10
|
+
stale_while_revalidate = configs.Integer()
|
|
11
|
+
stale_if_error = configs.Integer()
|
|
12
|
+
immutable = configs.Boolean(default=False)
|
|
13
|
+
must_understand = configs.Boolean(default=False)
|
|
14
|
+
no_cache = configs.Boolean(default=False)
|
|
15
|
+
no_store = configs.Boolean(default=False)
|
|
16
|
+
no_transform = configs.Boolean(default=False)
|
|
17
|
+
private = configs.Boolean(default=False)
|
|
18
|
+
public = configs.Boolean(default=False)
|
|
18
19
|
|
|
19
20
|
numbers: list[str] = [
|
|
20
21
|
"max_age",
|
|
@@ -32,7 +33,7 @@ class CacheControl(SecurityHeader):
|
|
|
32
33
|
"public",
|
|
33
34
|
]
|
|
34
35
|
|
|
35
|
-
@
|
|
36
|
+
@decorators.parameters_to_properties
|
|
36
37
|
def __init__(
|
|
37
38
|
self,
|
|
38
39
|
max_age: int | None = None,
|
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from clearskies import configs, decorators
|
|
3
4
|
from clearskies.security_header import SecurityHeader
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Cors(SecurityHeader):
|
|
7
|
-
origin =
|
|
8
|
-
methods =
|
|
9
|
-
headers =
|
|
10
|
-
max_age =
|
|
11
|
-
credentials =
|
|
12
|
-
expose_headers =
|
|
8
|
+
origin = configs.String()
|
|
9
|
+
methods = configs.StringList(default=[])
|
|
10
|
+
headers = configs.StringList(default=[])
|
|
11
|
+
max_age = configs.Integer(default=5)
|
|
12
|
+
credentials = configs.Boolean(default=False)
|
|
13
|
+
expose_headers = configs.StringList(default=[])
|
|
13
14
|
is_cors = True
|
|
14
15
|
|
|
15
|
-
@
|
|
16
|
+
@decorators.parameters_to_properties
|
|
16
17
|
def __init__(
|
|
17
18
|
self,
|
|
18
19
|
credentials: bool = False,
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from clearskies import configs, decorators
|
|
3
4
|
from clearskies.security_header import SecurityHeader
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Csp(SecurityHeader):
|
|
7
8
|
header_name = "content-security-policy"
|
|
8
|
-
default_src =
|
|
9
|
-
script_src =
|
|
10
|
-
style_src =
|
|
11
|
-
img_src =
|
|
12
|
-
connect_src =
|
|
13
|
-
font_src =
|
|
14
|
-
object_src =
|
|
15
|
-
media_src =
|
|
16
|
-
frame_src =
|
|
17
|
-
sandbox =
|
|
18
|
-
report_uri =
|
|
19
|
-
child_src =
|
|
20
|
-
form_action =
|
|
21
|
-
frame_ancestors =
|
|
22
|
-
plugin_types =
|
|
23
|
-
base_uri =
|
|
24
|
-
report_to =
|
|
25
|
-
worker_src =
|
|
26
|
-
manifest_src =
|
|
27
|
-
prefetch_src =
|
|
28
|
-
navigate_to =
|
|
9
|
+
default_src = configs.String()
|
|
10
|
+
script_src = configs.String()
|
|
11
|
+
style_src = configs.String()
|
|
12
|
+
img_src = configs.String()
|
|
13
|
+
connect_src = configs.String()
|
|
14
|
+
font_src = configs.String()
|
|
15
|
+
object_src = configs.String()
|
|
16
|
+
media_src = configs.String()
|
|
17
|
+
frame_src = configs.String()
|
|
18
|
+
sandbox = configs.String()
|
|
19
|
+
report_uri = configs.String()
|
|
20
|
+
child_src = configs.String()
|
|
21
|
+
form_action = configs.String()
|
|
22
|
+
frame_ancestors = configs.String()
|
|
23
|
+
plugin_types = configs.String()
|
|
24
|
+
base_uri = configs.String()
|
|
25
|
+
report_to = configs.String()
|
|
26
|
+
worker_src = configs.String()
|
|
27
|
+
manifest_src = configs.String()
|
|
28
|
+
prefetch_src = configs.String()
|
|
29
|
+
navigate_to = configs.String()
|
|
29
30
|
|
|
30
31
|
directives = [
|
|
31
32
|
"default_src",
|
|
@@ -51,7 +52,7 @@ class Csp(SecurityHeader):
|
|
|
51
52
|
"navigate_to",
|
|
52
53
|
]
|
|
53
54
|
|
|
54
|
-
@
|
|
55
|
+
@decorators.parameters_to_properties
|
|
55
56
|
def __init__(
|
|
56
57
|
self,
|
|
57
58
|
default_src: str = "",
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from clearskies import configs, decorators
|
|
3
4
|
from clearskies.security_header import SecurityHeader
|
|
4
5
|
|
|
5
6
|
|
|
6
7
|
class Hsts(SecurityHeader):
|
|
7
|
-
max_age =
|
|
8
|
-
include_sub_domains =
|
|
8
|
+
max_age = configs.Integer(default=31536000)
|
|
9
|
+
include_sub_domains = configs.Boolean()
|
|
9
10
|
|
|
10
|
-
@
|
|
11
|
+
@decorators.parameters_to_properties
|
|
11
12
|
def __init__(
|
|
12
13
|
self,
|
|
13
14
|
max_age: int = 31536000,
|
clearskies/typing.py
CHANGED
clearskies/validator.py
CHANGED
|
@@ -6,13 +6,12 @@ from typing import TYPE_CHECKING, Any
|
|
|
6
6
|
from clearskies import configurable
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
9
|
-
import
|
|
10
|
-
import clearskies.model
|
|
9
|
+
from clearskies import Column, Model
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class Validator(ABC, configurable.Configurable):
|
|
14
13
|
"""
|
|
15
|
-
Attach input validation rules to columns
|
|
14
|
+
Attach input validation rules to columns.
|
|
16
15
|
|
|
17
16
|
The validators provide a way to attach input validation logic to columns. The columns themselves already
|
|
18
17
|
provide basic validation (making sure strings are strings, integers are integers, etc...) but these classes
|
|
@@ -26,12 +25,12 @@ class Validator(ABC, configurable.Configurable):
|
|
|
26
25
|
is_unique = False
|
|
27
26
|
is_required = False
|
|
28
27
|
|
|
29
|
-
def __call__(self, model:
|
|
28
|
+
def __call__(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
30
29
|
return self.check(model, column_name, data)
|
|
31
30
|
|
|
32
31
|
@abstractmethod
|
|
33
|
-
def check(self, model:
|
|
32
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
34
33
|
pass
|
|
35
34
|
|
|
36
|
-
def additional_write_columns(self, is_create=False) -> dict[str,
|
|
35
|
+
def additional_write_columns(self, is_create=False) -> dict[str, Column]:
|
|
37
36
|
return {}
|
|
@@ -5,31 +5,30 @@ from typing import TYPE_CHECKING, Any
|
|
|
5
5
|
|
|
6
6
|
import dateparser
|
|
7
7
|
|
|
8
|
-
import
|
|
9
|
-
import clearskies.decorators
|
|
8
|
+
from clearskies import configs, decorators
|
|
10
9
|
from clearskies.validator import Validator
|
|
11
10
|
|
|
12
11
|
if TYPE_CHECKING:
|
|
13
|
-
import
|
|
12
|
+
from clearskies import Model
|
|
14
13
|
|
|
15
14
|
|
|
16
15
|
class AfterColumn(Validator):
|
|
17
16
|
"""The name of the other date column for comparison."""
|
|
18
17
|
|
|
19
|
-
other_column_name =
|
|
18
|
+
other_column_name = configs.String(default="", required=True)
|
|
20
19
|
|
|
21
20
|
"""
|
|
22
21
|
If true, then this column is allowed to be eqaul to the other column.
|
|
23
22
|
"""
|
|
24
|
-
allow_equal =
|
|
23
|
+
allow_equal = configs.Boolean(default=False)
|
|
25
24
|
|
|
26
|
-
@
|
|
25
|
+
@decorators.parameters_to_properties
|
|
27
26
|
def __init__(self, other_column_name: str, allow_equal: bool = False):
|
|
28
27
|
self.other_column_name = other_column_name
|
|
29
28
|
self.allow_equal = allow_equal
|
|
30
29
|
self.finalize_and_validate_configuration()
|
|
31
30
|
|
|
32
|
-
def check(self, model:
|
|
31
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
33
32
|
# we won't check anything for missing values (columns should be required if that is an issue)
|
|
34
33
|
if not data.get(column_name):
|
|
35
34
|
return ""
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import datetime
|
|
4
|
-
from collections import OrderedDict
|
|
5
4
|
from typing import TYPE_CHECKING, Any
|
|
6
5
|
|
|
7
6
|
import dateparser
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
import clearskies.decorators
|
|
11
|
-
import clearskies.di
|
|
8
|
+
from clearskies.di import InjectableProperties, inject
|
|
12
9
|
from clearskies.validator import Validator
|
|
13
10
|
|
|
14
11
|
if TYPE_CHECKING:
|
|
15
|
-
import
|
|
12
|
+
from clearskies import Model
|
|
16
13
|
|
|
17
14
|
|
|
18
|
-
class InTheFuture(Validator,
|
|
19
|
-
utcnow =
|
|
15
|
+
class InTheFuture(Validator, InjectableProperties):
|
|
16
|
+
utcnow = inject.Utcnow()
|
|
20
17
|
|
|
21
|
-
def check(self, model:
|
|
18
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
22
19
|
if not data.get(column_name):
|
|
23
20
|
return ""
|
|
24
21
|
|
|
@@ -1,24 +1,21 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import datetime
|
|
4
|
-
from collections import OrderedDict
|
|
5
4
|
from typing import TYPE_CHECKING, Any
|
|
6
5
|
|
|
7
6
|
import dateparser
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
import clearskies.decorators
|
|
11
|
-
import clearskies.di
|
|
8
|
+
from clearskies.di import InjectableProperties, inject
|
|
12
9
|
from clearskies.validator import Validator
|
|
13
10
|
|
|
14
11
|
if TYPE_CHECKING:
|
|
15
|
-
import
|
|
12
|
+
from clearskies import Model
|
|
16
13
|
|
|
17
14
|
|
|
18
|
-
class InThePast(Validator,
|
|
19
|
-
utcnow =
|
|
15
|
+
class InThePast(Validator, InjectableProperties):
|
|
16
|
+
utcnow = inject.Utcnow()
|
|
20
17
|
|
|
21
|
-
def check(self, model:
|
|
18
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
22
19
|
if not data.get(column_name):
|
|
23
20
|
return ""
|
|
24
21
|
|
|
@@ -1,23 +1,22 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import datetime
|
|
4
3
|
from typing import TYPE_CHECKING, Any
|
|
5
4
|
|
|
6
|
-
import
|
|
5
|
+
from clearskies import configs
|
|
7
6
|
from clearskies.validator import Validator
|
|
8
7
|
|
|
9
8
|
if TYPE_CHECKING:
|
|
10
|
-
import
|
|
9
|
+
from clearskies import Model
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class MaximumLength(Validator):
|
|
14
|
-
maximum_length =
|
|
13
|
+
maximum_length = configs.Integer(required=True)
|
|
15
14
|
|
|
16
15
|
def __init__(self, maximum_length: int):
|
|
17
16
|
self.maximum_length = maximum_length
|
|
18
17
|
self.finalize_and_validate_configuration()
|
|
19
18
|
|
|
20
|
-
def check(self, model:
|
|
19
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
20
|
# we won't check anything for missing values (columns should be required if that is an issue)
|
|
22
21
|
if not data.get(column_name):
|
|
23
22
|
return ""
|
|
@@ -3,21 +3,21 @@ from __future__ import annotations
|
|
|
3
3
|
import datetime
|
|
4
4
|
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
from clearskies import configs
|
|
7
7
|
from clearskies.validator import Validator
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
import
|
|
10
|
+
from clearskies import Model
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class MaximumValue(Validator):
|
|
14
|
-
maximum_value =
|
|
14
|
+
maximum_value = configs.Integer(required=True)
|
|
15
15
|
|
|
16
16
|
def __init__(self, maximum_value: int):
|
|
17
17
|
self.maximum_value = maximum_value
|
|
18
18
|
self.finalize_and_validate_configuration()
|
|
19
19
|
|
|
20
|
-
def check(self, model:
|
|
20
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
21
|
if column_name not in data:
|
|
22
22
|
return ""
|
|
23
23
|
try:
|
|
@@ -3,21 +3,21 @@ from __future__ import annotations
|
|
|
3
3
|
import datetime
|
|
4
4
|
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
from clearskies import configs
|
|
7
7
|
from clearskies.validator import Validator
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
import
|
|
10
|
+
from clearskies import Model
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class MinimumLength(Validator):
|
|
14
|
-
minimum_length =
|
|
14
|
+
minimum_length = configs.Integer(required=True)
|
|
15
15
|
|
|
16
16
|
def __init__(self, minimum_length: int):
|
|
17
17
|
self.minimum_length = minimum_length
|
|
18
18
|
self.finalize_and_validate_configuration()
|
|
19
19
|
|
|
20
|
-
def check(self, model:
|
|
20
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
21
|
# we won't check anything for missing values (columns should be required if that is an issue)
|
|
22
22
|
if not data.get(column_name):
|
|
23
23
|
return ""
|
|
@@ -3,21 +3,21 @@ from __future__ import annotations
|
|
|
3
3
|
import datetime
|
|
4
4
|
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
|
-
import
|
|
6
|
+
from clearskies import configs
|
|
7
7
|
from clearskies.validator import Validator
|
|
8
8
|
|
|
9
9
|
if TYPE_CHECKING:
|
|
10
|
-
import
|
|
10
|
+
from clearskies import Model
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class MinimumValue(Validator):
|
|
14
|
-
minimum_value =
|
|
14
|
+
minimum_value = configs.Integer(required=True)
|
|
15
15
|
|
|
16
16
|
def __init__(self, minimum_value: int):
|
|
17
17
|
self.minimum_value = minimum_value
|
|
18
18
|
self.finalize_and_validate_configuration()
|
|
19
19
|
|
|
20
|
-
def check(self, model:
|
|
20
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
21
21
|
if column_name not in data:
|
|
22
22
|
return ""
|
|
23
23
|
try:
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import datetime
|
|
4
3
|
from typing import TYPE_CHECKING, Any
|
|
5
4
|
|
|
6
|
-
import clearskies.configs
|
|
7
5
|
from clearskies.validator import Validator
|
|
8
6
|
|
|
9
7
|
if TYPE_CHECKING:
|
|
10
|
-
import
|
|
8
|
+
from clearskies import Model
|
|
11
9
|
|
|
12
10
|
|
|
13
11
|
class Required(Validator):
|
|
14
12
|
is_required = True
|
|
15
13
|
|
|
16
|
-
def check(self, model:
|
|
14
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
17
15
|
# you'd think that "required" is straight forward and we want an input error if it isn't found.
|
|
18
16
|
# this isn't strictly true though. If the model already exists, the column has a value in the model already,
|
|
19
17
|
# and the column is completely missing from the input data, then it is actually perfectly fine (because
|
|
@@ -6,21 +6,20 @@ from typing import TYPE_CHECKING, Any
|
|
|
6
6
|
|
|
7
7
|
import dateparser
|
|
8
8
|
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
import clearskies.di
|
|
9
|
+
from clearskies import configs, decorators
|
|
10
|
+
from clearskies.di import InjectableProperties, inject
|
|
12
11
|
from clearskies.validator import Validator
|
|
13
12
|
|
|
14
13
|
if TYPE_CHECKING:
|
|
15
|
-
import
|
|
14
|
+
from clearskies import Model
|
|
16
15
|
|
|
17
16
|
|
|
18
|
-
class Timedelta(Validator,
|
|
19
|
-
timedelta =
|
|
17
|
+
class Timedelta(Validator, InjectableProperties):
|
|
18
|
+
timedelta = configs.Timedelta(default=None)
|
|
20
19
|
|
|
21
|
-
utcnow =
|
|
20
|
+
utcnow = inject.Utcnow()
|
|
22
21
|
|
|
23
|
-
@
|
|
22
|
+
@decorators.parameters_to_properties
|
|
24
23
|
def __init__(self, timedelta: datetime.timedelta):
|
|
25
24
|
self.finalize_and_validate_configuration()
|
|
26
25
|
|
|
@@ -44,7 +43,7 @@ class Timedelta(Validator, clearskies.di.InjectableProperties):
|
|
|
44
43
|
parts.append(f"{amount} {name}" + ("s" if amount != 1 else ""))
|
|
45
44
|
return ", ".join(parts)
|
|
46
45
|
|
|
47
|
-
def check(self, model:
|
|
46
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
48
47
|
if not data.get(column_name):
|
|
49
48
|
return ""
|
|
50
49
|
|
clearskies/validators/unique.py
CHANGED
|
@@ -3,17 +3,16 @@ from __future__ import annotations
|
|
|
3
3
|
import datetime
|
|
4
4
|
from typing import TYPE_CHECKING, Any
|
|
5
5
|
|
|
6
|
-
import clearskies.configs
|
|
7
6
|
from clearskies.validator import Validator
|
|
8
7
|
|
|
9
8
|
if TYPE_CHECKING:
|
|
10
|
-
import
|
|
9
|
+
from clearskies import Model
|
|
11
10
|
|
|
12
11
|
|
|
13
12
|
class Unique(Validator):
|
|
14
13
|
is_unique = True
|
|
15
14
|
|
|
16
|
-
def check(self, model:
|
|
15
|
+
def check(self, model: Model, column_name: str, data: dict[str, Any]) -> str:
|
|
17
16
|
# Unique is mildly tricky. We obviously want to search the backend for the new value,
|
|
18
17
|
# but we need to first skip this if our column is not being set, or if we're editing
|
|
19
18
|
# the model and nothing is changing.
|