clear-skies 2.0.7__py3-none-any.whl → 2.0.8__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.

Files changed (148) hide show
  1. {clear_skies-2.0.7.dist-info → clear_skies-2.0.8.dist-info}/METADATA +1 -1
  2. clear_skies-2.0.8.dist-info/RECORD +252 -0
  3. clearskies/__init__.py +2 -2
  4. clearskies/authentication/authentication.py +1 -3
  5. clearskies/authentication/authorization.py +12 -5
  6. clearskies/authentication/authorization_pass_through.py +5 -3
  7. clearskies/authentication/jwks.py +25 -23
  8. clearskies/authentication/secret_bearer.py +15 -17
  9. clearskies/autodoc/schema/schema.py +1 -1
  10. clearskies/backends/api_backend.py +50 -56
  11. clearskies/backends/backend.py +14 -14
  12. clearskies/backends/cursor_backend.py +17 -23
  13. clearskies/backends/memory_backend.py +27 -30
  14. clearskies/backends/secrets_backend.py +13 -18
  15. clearskies/column.py +44 -56
  16. clearskies/columns/audit.py +14 -13
  17. clearskies/columns/belongs_to_id.py +10 -15
  18. clearskies/columns/belongs_to_model.py +6 -9
  19. clearskies/columns/belongs_to_self.py +13 -9
  20. clearskies/columns/boolean.py +13 -16
  21. clearskies/columns/category_tree.py +9 -11
  22. clearskies/columns/category_tree_children.py +2 -3
  23. clearskies/columns/category_tree_descendants.py +1 -1
  24. clearskies/columns/created.py +8 -11
  25. clearskies/columns/created_by_authorization_data.py +7 -9
  26. clearskies/columns/created_by_header.py +12 -8
  27. clearskies/columns/created_by_ip.py +6 -8
  28. clearskies/columns/created_by_routing_data.py +12 -7
  29. clearskies/columns/created_by_user_agent.py +6 -9
  30. clearskies/columns/date.py +12 -14
  31. clearskies/columns/datetime.py +19 -17
  32. clearskies/columns/email.py +3 -1
  33. clearskies/columns/float.py +10 -14
  34. clearskies/columns/has_many.py +8 -10
  35. clearskies/columns/has_many_self.py +13 -7
  36. clearskies/columns/has_one.py +2 -0
  37. clearskies/columns/integer.py +9 -11
  38. clearskies/columns/json.py +10 -12
  39. clearskies/columns/many_to_many_ids.py +14 -16
  40. clearskies/columns/many_to_many_ids_with_data.py +16 -16
  41. clearskies/columns/many_to_many_models.py +5 -7
  42. clearskies/columns/many_to_many_pivots.py +3 -5
  43. clearskies/columns/phone.py +12 -9
  44. clearskies/columns/select.py +12 -9
  45. clearskies/columns/string.py +1 -1
  46. clearskies/columns/timestamp.py +15 -15
  47. clearskies/columns/updated.py +8 -10
  48. clearskies/columns/uuid.py +7 -10
  49. clearskies/configs/any.py +2 -0
  50. clearskies/configs/any_dict.py +2 -0
  51. clearskies/configs/any_dict_or_callable.py +2 -0
  52. clearskies/configs/boolean.py +2 -0
  53. clearskies/configs/boolean_or_callable.py +2 -0
  54. clearskies/configs/callable_config.py +2 -0
  55. clearskies/configs/config.py +2 -0
  56. clearskies/configs/datetime.py +2 -0
  57. clearskies/configs/datetime_or_callable.py +2 -0
  58. clearskies/configs/float.py +2 -0
  59. clearskies/configs/float_or_callable.py +2 -0
  60. clearskies/configs/integer.py +2 -0
  61. clearskies/configs/integer_or_callable.py +2 -0
  62. clearskies/configs/list_any_dict.py +2 -0
  63. clearskies/configs/list_any_dict_or_callable.py +2 -0
  64. clearskies/configs/model_column.py +2 -0
  65. clearskies/configs/model_columns.py +2 -0
  66. clearskies/configs/model_destination_name.py +2 -1
  67. clearskies/configs/model_to_id_column.py +2 -0
  68. clearskies/configs/readable_model_column.py +2 -0
  69. clearskies/configs/readable_model_columns.py +2 -0
  70. clearskies/configs/searchable_model_columns.py +2 -0
  71. clearskies/configs/select.py +2 -0
  72. clearskies/configs/select_list.py +2 -0
  73. clearskies/configs/string.py +2 -0
  74. clearskies/configs/string_dict.py +2 -0
  75. clearskies/configs/string_list.py +2 -0
  76. clearskies/configs/string_list_or_callable.py +2 -0
  77. clearskies/configs/timedelta.py +2 -0
  78. clearskies/configs/timezone.py +2 -0
  79. clearskies/configs/url.py +2 -0
  80. clearskies/configs/writeable_model_column.py +2 -0
  81. clearskies/configs/writeable_model_columns.py +2 -0
  82. clearskies/configurable.py +2 -0
  83. clearskies/contexts/cli.py +9 -1
  84. clearskies/contexts/context.py +13 -14
  85. clearskies/contexts/wsgi.py +12 -10
  86. clearskies/contexts/wsgi_ref.py +12 -6
  87. clearskies/decorators.py +1 -1
  88. clearskies/decorators.pyi +10 -0
  89. clearskies/di/di.py +7 -6
  90. clearskies/di/inject/by_class.py +2 -0
  91. clearskies/di/inject/by_name.py +2 -0
  92. clearskies/di/inject/di.py +2 -0
  93. clearskies/di/inject/environment.py +1 -1
  94. clearskies/di/inject/now.py +2 -0
  95. clearskies/di/inject/requests.py +2 -0
  96. clearskies/di/inject/secrets.py +2 -2
  97. clearskies/di/inject/utcnow.py +2 -0
  98. clearskies/di/inject/uuid.py +2 -2
  99. clearskies/end.py +45 -7
  100. clearskies/endpoint.py +43 -59
  101. clearskies/endpoint_group.py +15 -18
  102. clearskies/endpoints/advanced_search.py +19 -26
  103. clearskies/endpoints/callable.py +10 -16
  104. clearskies/endpoints/create.py +6 -10
  105. clearskies/endpoints/delete.py +5 -11
  106. clearskies/endpoints/get.py +11 -15
  107. clearskies/endpoints/health_check.py +9 -11
  108. clearskies/endpoints/list.py +29 -36
  109. clearskies/endpoints/restful_api.py +43 -53
  110. clearskies/endpoints/schema.py +14 -18
  111. clearskies/endpoints/simple_search.py +5 -12
  112. clearskies/endpoints/update.py +6 -11
  113. clearskies/environment.py +2 -0
  114. clearskies/input_outputs/cli.py +2 -0
  115. clearskies/input_outputs/headers.py +2 -0
  116. clearskies/input_outputs/input_output.py +15 -15
  117. clearskies/input_outputs/programmatic.py +2 -2
  118. clearskies/input_outputs/wsgi.py +2 -2
  119. clearskies/model.py +120 -25
  120. clearskies/query/query.py +1 -4
  121. clearskies/secrets/__init__.py +2 -1
  122. clearskies/secrets/akeyless.py +12 -10
  123. clearskies/secrets/secrets.py +7 -2
  124. clearskies/security_header.py +4 -2
  125. clearskies/security_headers/cache_control.py +15 -14
  126. clearskies/security_headers/cors.py +10 -9
  127. clearskies/security_headers/csp.py +25 -24
  128. clearskies/security_headers/hsts.py +6 -5
  129. clearskies/typing.py +1 -1
  130. clearskies/validator.py +5 -6
  131. clearskies/validators/after_column.py +6 -7
  132. clearskies/validators/before_column.py +2 -0
  133. clearskies/validators/in_the_future.py +5 -8
  134. clearskies/validators/in_the_future_at_least.py +2 -0
  135. clearskies/validators/in_the_future_at_most.py +2 -0
  136. clearskies/validators/in_the_past.py +5 -8
  137. clearskies/validators/in_the_past_at_least.py +2 -0
  138. clearskies/validators/in_the_past_at_most.py +2 -0
  139. clearskies/validators/maximum_length.py +4 -5
  140. clearskies/validators/maximum_value.py +4 -4
  141. clearskies/validators/minimum_length.py +4 -4
  142. clearskies/validators/minimum_value.py +4 -4
  143. clearskies/validators/required.py +2 -4
  144. clearskies/validators/timedelta.py +8 -9
  145. clearskies/validators/unique.py +2 -3
  146. clear_skies-2.0.7.dist-info/RECORD +0 -251
  147. {clear_skies-2.0.7.dist-info → clear_skies-2.0.8.dist-info}/WHEEL +0 -0
  148. {clear_skies-2.0.7.dist-info → clear_skies-2.0.8.dist-info}/licenses/LICENSE +0 -0
@@ -3,8 +3,7 @@ from __future__ import annotations
3
3
  from collections import OrderedDict
4
4
  from typing import TYPE_CHECKING, Any, Self, overload
5
5
 
6
- import clearskies.decorators
7
- from clearskies import configs
6
+ from clearskies import configs, decorators
8
7
  from clearskies.column import Column
9
8
  from clearskies.columns.belongs_to_id import BelongsToId
10
9
  from clearskies.functional import validations
@@ -19,10 +18,10 @@ class BelongsToModel(Column):
19
18
  """ The name of the belongs to column we are connected to. """
20
19
  belongs_to_column_name = configs.ModelColumn(required=True)
21
20
 
22
- is_temporary = clearskies.configs.boolean.Boolean(default=True)
21
+ is_temporary = configs.boolean.Boolean(default=True)
23
22
  _descriptor_config_map = None
24
23
 
25
- @clearskies.decorators.parameters_to_properties
24
+ @decorators.parameters_to_properties
26
25
  def __init__(
27
26
  self,
28
27
  belongs_to_column_name: str,
@@ -45,11 +44,11 @@ class BelongsToModel(Column):
45
44
  belongs_to_column.model_column_name = name
46
45
 
47
46
  @overload
48
- def __get__(self, instance: None, cls: type[Model]) -> Self:
47
+ def __get__(self, model: None, cls: type[Model]) -> Self:
49
48
  pass
50
49
 
51
50
  @overload
52
- def __get__(self, instance: Model, cls: type[Model]) -> Model:
51
+ def __get__(self, model: Model, cls: type[Model]) -> Model:
53
52
  pass
54
53
 
55
54
  def __get__(self, model, cls):
@@ -106,9 +105,7 @@ class BelongsToModel(Column):
106
105
  def join_table_alias(self) -> str:
107
106
  return getattr(self.model_class, self.belongs_to_column_name).join_table_alias()
108
107
 
109
- def add_search(
110
- self, model: clearskies.model.Model, value: str, operator: str = "", relationship_reference: str = ""
111
- ) -> clearskies.model.Model:
108
+ def add_search(self, model: Model, value: str, operator: str = "", relationship_reference: str = "") -> Model:
112
109
  return getattr(self.model_class, self.belongs_to_column_name).add_search(
113
110
  model, value, operator, relationship_reference=relationship_reference
114
111
  )
@@ -1,9 +1,13 @@
1
- from typing import Callable
1
+ from __future__ import annotations
2
2
 
3
- import clearskies.decorators
4
- import clearskies.typing
3
+ from typing import TYPE_CHECKING, Callable
4
+
5
+ from clearskies import decorators
5
6
  from clearskies.columns.belongs_to_id import BelongsToId
6
7
 
8
+ if TYPE_CHECKING:
9
+ from clearskies import typing
10
+
7
11
 
8
12
  class BelongsToSelf(BelongsToId):
9
13
  """
@@ -69,22 +73,22 @@ class BelongsToSelf(BelongsToId):
69
73
 
70
74
  _descriptor_config_map = None
71
75
 
72
- @clearskies.decorators.parameters_to_properties
76
+ @decorators.parameters_to_properties
73
77
  def __init__(
74
78
  self,
75
79
  readable_parent_columns: list[str] = [],
76
80
  join_type: str | None = None,
77
- where: clearskies.typing.condition | list[clearskies.typing.condition] = [],
81
+ where: typing.condition | list[typing.condition] = [],
78
82
  default: str | None = None,
79
83
  setable: str | Callable | None = None,
80
84
  is_readable: bool = True,
81
85
  is_writeable: bool = True,
82
86
  is_searchable: bool = True,
83
87
  is_temporary: bool = False,
84
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
85
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
86
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
87
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
88
+ validators: typing.validator | list[typing.validator] = [],
89
+ on_change_pre_save: typing.action | list[typing.action] = [],
90
+ on_change_post_save: typing.action | list[typing.action] = [],
91
+ on_change_save_finished: typing.action | list[typing.action] = [],
88
92
  created_by_source_type: str = "",
89
93
  created_by_source_key: str = "",
90
94
  created_by_source_strict: bool = True,
@@ -2,17 +2,14 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Callable, Self, overload
4
4
 
5
- import clearskies.configs.actions
6
- import clearskies.decorators
7
- import clearskies.typing
8
- from clearskies import configs
5
+ from clearskies import configs, decorators
9
6
  from clearskies.autodoc.schema import Boolean as AutoDocBoolean
10
- from clearskies.autodoc.schema import Schema as AutoDocSchema
11
7
  from clearskies.column import Column
12
- from clearskies.query import Condition
13
8
 
14
9
  if TYPE_CHECKING:
15
- from clearskies import Model
10
+ from clearskies import Model, typing
11
+ from clearskies.autodoc.schema import Schema as AutoDocSchema
12
+ from clearskies.query import Condition
16
13
 
17
14
 
18
15
  class Boolean(Column):
@@ -21,12 +18,12 @@ class Boolean(Column):
21
18
  """
22
19
  Actions to trigger when the column changes to True
23
20
  """
24
- on_true = clearskies.configs.actions.Actions(default=[])
21
+ on_true = configs.actions.Actions(default=[])
25
22
 
26
23
  """
27
24
  Actions to trigger when the column changes to False
28
25
  """
29
- on_false = clearskies.configs.actions.Actions(default=[])
26
+ on_false = configs.actions.Actions(default=[])
30
27
 
31
28
  """
32
29
  The class to use when documenting this column
@@ -38,7 +35,7 @@ class Boolean(Column):
38
35
  setable = configs.BooleanOrCallable() # type: ignore
39
36
  _descriptor_config_map = None
40
37
 
41
- @clearskies.decorators.parameters_to_properties
38
+ @decorators.parameters_to_properties
42
39
  def __init__(
43
40
  self,
44
41
  default: bool | None = None,
@@ -47,12 +44,12 @@ class Boolean(Column):
47
44
  is_writeable: bool = True,
48
45
  is_searchable: bool = True,
49
46
  is_temporary: bool = False,
50
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
51
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
52
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
53
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
54
- on_true: clearskies.typing.action | list[clearskies.typing.action] = [],
55
- on_false: clearskies.typing.action | list[clearskies.typing.action] = [],
47
+ validators: typing.validator | list[typing.validator] = [],
48
+ on_change_pre_save: typing.action | list[typing.action] = [],
49
+ on_change_post_save: typing.action | list[typing.action] = [],
50
+ on_change_save_finished: typing.action | list[typing.action] = [],
51
+ on_true: typing.action | list[typing.action] = [],
52
+ on_false: typing.action | list[typing.action] = [],
56
53
  created_by_source_type: str = "",
57
54
  created_by_source_key: str = "",
58
55
  created_by_source_strict: bool = True,
@@ -2,13 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any, Callable
4
4
 
5
- import clearskies.decorators
6
- import clearskies.typing
7
- from clearskies import configs
5
+ from clearskies import configs, decorators
8
6
  from clearskies.columns.belongs_to_id import BelongsToId
9
7
 
10
8
  if TYPE_CHECKING:
11
- from clearskies import Model
9
+ from clearskies import Model, typing
12
10
 
13
11
 
14
12
  class CategoryTree(BelongsToId):
@@ -163,7 +161,7 @@ class CategoryTree(BelongsToId):
163
161
 
164
162
  _descriptor_config_map = None
165
163
 
166
- @clearskies.decorators.parameters_to_properties
164
+ @decorators.parameters_to_properties
167
165
  def __init__(
168
166
  self,
169
167
  tree_model_class,
@@ -175,17 +173,17 @@ class CategoryTree(BelongsToId):
175
173
  load_relatives_strategy: str = "join",
176
174
  readable_parent_columns: list[str] = [],
177
175
  join_type: str | None = None,
178
- where: clearskies.typing.condition | list[clearskies.typing.condition] = [],
176
+ where: typing.condition | list[typing.condition] = [],
179
177
  default: str | None = None,
180
178
  setable: str | Callable | None = None,
181
179
  is_readable: bool = True,
182
180
  is_writeable: bool = True,
183
181
  is_searchable: bool = True,
184
182
  is_temporary: bool = False,
185
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
186
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
187
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
188
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
183
+ validators: typing.validator | list[typing.validator] = [],
184
+ on_change_pre_save: typing.action | list[typing.action] = [],
185
+ on_change_post_save: typing.action | list[typing.action] = [],
186
+ on_change_save_finished: typing.action | list[typing.action] = [],
189
187
  created_by_source_type: str = "",
190
188
  created_by_source_key: str = "",
191
189
  created_by_source_strict: bool = True,
@@ -216,7 +214,7 @@ class CategoryTree(BelongsToId):
216
214
  self.update_tree_table(model, id, model.latest(self.name, data))
217
215
  return
218
216
 
219
- def force_tree_update(self, model: Model):
217
+ def force_tree_update(self, model: Model) -> None:
220
218
  self.update_tree_table(model, getattr(model, model.id_column_name), getattr(model, self.name))
221
219
 
222
220
  def update_tree_table(self, model: Model, child_id: int | str, direct_parent_id: int | str) -> None:
@@ -2,8 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Self, overload
4
4
 
5
- import clearskies.decorators
6
- from clearskies import configs
5
+ from clearskies import configs, decorators
7
6
  from clearskies.column import Column
8
7
  from clearskies.columns import CategoryTree
9
8
 
@@ -36,7 +35,7 @@ class CategoryTreeChildren(Column):
36
35
  is_searchable = configs.Boolean(default=False)
37
36
  _descriptor_config_map = None
38
37
 
39
- @clearskies.decorators.parameters_to_properties
38
+ @decorators.parameters_to_properties
40
39
  def __init__(
41
40
  self,
42
41
  category_tree_column_name: str,
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Self, Type, overload
3
+ from typing import TYPE_CHECKING, Self, overload
4
4
 
5
5
  from clearskies.columns import CategoryTreeChildren
6
6
 
@@ -1,16 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
- import clearskies.decorators
7
- import clearskies.di
8
- import clearskies.typing
9
- from clearskies import configs
5
+ from clearskies import configs, decorators
10
6
  from clearskies.columns.datetime import Datetime
7
+ from clearskies.di import inject
11
8
 
12
9
  if TYPE_CHECKING:
13
- from clearskies import Model
10
+ from clearskies import Model, typing
14
11
 
15
12
 
16
13
  class Created(Datetime):
@@ -66,9 +63,9 @@ class Created(Datetime):
66
63
  is_writeable = configs.Boolean(default=False)
67
64
  _descriptor_config_map = None
68
65
 
69
- now = clearskies.di.inject.Now()
66
+ now = inject.Now()
70
67
 
71
- @clearskies.decorators.parameters_to_properties
68
+ @decorators.parameters_to_properties
72
69
  def __init__(
73
70
  self,
74
71
  date_format: str = "%Y-%m-%d %H:%M:%S",
@@ -77,9 +74,9 @@ class Created(Datetime):
77
74
  is_readable: bool = True,
78
75
  is_searchable: bool = True,
79
76
  is_temporary: bool = False,
80
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
81
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
82
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
77
+ on_change_pre_save: typing.action | list[typing.action] = [],
78
+ on_change_post_save: typing.action | list[typing.action] = [],
79
+ on_change_save_finished: typing.action | list[typing.action] = [],
83
80
  ):
84
81
  pass
85
82
 
@@ -1,14 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any
3
+ from typing import TYPE_CHECKING
4
4
 
5
- import clearskies.decorators
6
- import clearskies.typing
7
- from clearskies import configs
5
+ from clearskies import configs, decorators
8
6
  from clearskies.columns.string import String
9
7
 
10
8
  if TYPE_CHECKING:
11
- from clearskies import Model
9
+ from clearskies import typing
12
10
 
13
11
 
14
12
  class CreatedByAuthorizationData(String):
@@ -100,7 +98,7 @@ class CreatedByAuthorizationData(String):
100
98
 
101
99
  _allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
102
100
 
103
- @clearskies.decorators.parameters_to_properties
101
+ @decorators.parameters_to_properties
104
102
  def __init__(
105
103
  self,
106
104
  authorization_data_key_name: str,
@@ -108,9 +106,9 @@ class CreatedByAuthorizationData(String):
108
106
  is_readable: bool = True,
109
107
  is_searchable: bool = True,
110
108
  is_temporary: bool = False,
111
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
112
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
113
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
109
+ on_change_pre_save: typing.action | list[typing.action] = [],
110
+ on_change_post_save: typing.action | list[typing.action] = [],
111
+ on_change_save_finished: typing.action | list[typing.action] = [],
114
112
  ):
115
113
  self.created_by_source_key = authorization_data_key_name
116
114
  self.created_by_source_type = "authorization_data"
@@ -1,8 +1,12 @@
1
- import clearskies.decorators
2
- import clearskies.typing
3
- from clearskies import configs
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from clearskies import configs, decorators
4
6
  from clearskies.columns.string import String
5
- from clearskies.query import Condition
7
+
8
+ if TYPE_CHECKING:
9
+ from clearskies import typing
6
10
 
7
11
 
8
12
  class CreatedByHeader(String):
@@ -83,7 +87,7 @@ class CreatedByHeader(String):
83
87
 
84
88
  _allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
85
89
 
86
- @clearskies.decorators.parameters_to_properties
90
+ @decorators.parameters_to_properties
87
91
  def __init__(
88
92
  self,
89
93
  header_name: str,
@@ -91,9 +95,9 @@ class CreatedByHeader(String):
91
95
  is_readable: bool = True,
92
96
  is_searchable: bool = True,
93
97
  is_temporary: bool = False,
94
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
95
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
96
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
98
+ on_change_pre_save: typing.action | list[typing.action] = [],
99
+ on_change_post_save: typing.action | list[typing.action] = [],
100
+ on_change_save_finished: typing.action | list[typing.action] = [],
97
101
  ):
98
102
  self.created_by_source_key = header_name
99
103
  self.created_by_source_type = "http_header"
@@ -2,13 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  from typing import TYPE_CHECKING, Any
4
4
 
5
- import clearskies.decorators
6
- import clearskies.typing
7
- from clearskies import configs
5
+ from clearskies import configs, decorators
8
6
  from clearskies.columns.string import String
9
7
 
10
8
  if TYPE_CHECKING:
11
- from clearskies import Model
9
+ from clearskies import Model, typing
12
10
 
13
11
 
14
12
  class CreatedByIp(String):
@@ -70,15 +68,15 @@ class CreatedByIp(String):
70
68
 
71
69
  _allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
72
70
 
73
- @clearskies.decorators.parameters_to_properties
71
+ @decorators.parameters_to_properties
74
72
  def __init__(
75
73
  self,
76
74
  is_readable: bool = True,
77
75
  is_searchable: bool = True,
78
76
  is_temporary: bool = False,
79
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
80
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
81
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
77
+ on_change_pre_save: typing.action | list[typing.action] = [],
78
+ on_change_post_save: typing.action | list[typing.action] = [],
79
+ on_change_save_finished: typing.action | list[typing.action] = [],
82
80
  ):
83
81
  pass
84
82
 
@@ -1,8 +1,13 @@
1
- import clearskies.decorators
2
- import clearskies.typing
3
- from clearskies import configs
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from clearskies import configs, decorators
4
6
  from clearskies.columns.string import String
5
7
 
8
+ if TYPE_CHECKING:
9
+ from clearskies import typing
10
+
6
11
 
7
12
  class CreatedByRoutingData(String):
8
13
  """
@@ -81,7 +86,7 @@ class CreatedByRoutingData(String):
81
86
 
82
87
  _allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
83
88
 
84
- @clearskies.decorators.parameters_to_properties
89
+ @decorators.parameters_to_properties
85
90
  def __init__(
86
91
  self,
87
92
  routing_path_name: str,
@@ -89,9 +94,9 @@ class CreatedByRoutingData(String):
89
94
  is_readable: bool = True,
90
95
  is_searchable: bool = True,
91
96
  is_temporary: bool = False,
92
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
93
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
94
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
97
+ on_change_pre_save: typing.action | list[typing.action] = [],
98
+ on_change_post_save: typing.action | list[typing.action] = [],
99
+ on_change_save_finished: typing.action | list[typing.action] = [],
95
100
  ):
96
101
  self.created_by_source_key = routing_path_name
97
102
  self.created_by_source_type = "routing_data"
@@ -1,15 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
- import datetime
4
3
  from typing import TYPE_CHECKING, Any
5
4
 
6
- import clearskies.decorators
7
- import clearskies.typing
8
- from clearskies import configs
5
+ from clearskies import configs, decorators
9
6
  from clearskies.columns.string import String
10
7
 
11
8
  if TYPE_CHECKING:
12
- from clearskies import Model
9
+ from clearskies import Model, typing
13
10
 
14
11
 
15
12
  class CreatedByUserAgent(String):
@@ -70,15 +67,15 @@ class CreatedByUserAgent(String):
70
67
 
71
68
  _allowed_search_operators = ["=", "in", "is not null", "is null", "like"]
72
69
 
73
- @clearskies.decorators.parameters_to_properties
70
+ @decorators.parameters_to_properties
74
71
  def __init__(
75
72
  self,
76
73
  is_readable: bool = True,
77
74
  is_searchable: bool = True,
78
75
  is_temporary: bool = False,
79
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
80
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
81
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
76
+ on_change_pre_save: typing.action | list[typing.action] = [],
77
+ on_change_post_save: typing.action | list[typing.action] = [],
78
+ on_change_save_finished: typing.action | list[typing.action] = [],
82
79
  ):
83
80
  pass
84
81
 
@@ -3,18 +3,16 @@ from __future__ import annotations
3
3
  import datetime
4
4
  from typing import TYPE_CHECKING, Any, Callable, Self, overload
5
5
 
6
- import dateparser # type: ignore
6
+ import dateparser
7
7
 
8
- import clearskies.decorators
9
- import clearskies.typing
10
- from clearskies import configs
8
+ from clearskies import configs, decorators
11
9
  from clearskies.autodoc.schema import Datetime as AutoDocDatetime
12
- from clearskies.autodoc.schema import Schema as AutoDocSchema
13
10
  from clearskies.columns.datetime import Datetime
14
- from clearskies.query import Condition
15
11
 
16
12
  if TYPE_CHECKING:
17
- from clearskies import Model
13
+ from clearskies import Model, typing
14
+ from clearskies.autodoc.schema import Schema as AutoDocSchema
15
+ from clearskies.query import Condition
18
16
 
19
17
 
20
18
  class Date(Datetime):
@@ -102,7 +100,7 @@ class Date(Datetime):
102
100
  auto_doc_class: type[AutoDocSchema] = AutoDocDatetime
103
101
  _descriptor_config_map = None
104
102
 
105
- @clearskies.decorators.parameters_to_properties
103
+ @decorators.parameters_to_properties
106
104
  def __init__(
107
105
  self,
108
106
  date_format: str = "%Y-%m-%d",
@@ -113,10 +111,10 @@ class Date(Datetime):
113
111
  is_writeable: bool = True,
114
112
  is_searchable: bool = True,
115
113
  is_temporary: bool = False,
116
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
117
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
118
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
119
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
114
+ validators: typing.validator | list[typing.validator] = [],
115
+ on_change_pre_save: typing.action | list[typing.action] = [],
116
+ on_change_post_save: typing.action | list[typing.action] = [],
117
+ on_change_save_finished: typing.action | list[typing.action] = [],
120
118
  created_by_source_type: str = "",
121
119
  created_by_source_key: str = "",
122
120
  created_by_source_strict: bool = True,
@@ -218,10 +216,10 @@ class Date(Datetime):
218
216
 
219
217
  if type(value_1) == str:
220
218
  value_1 = dateparser.parse(value_1)
221
- value_1 = datetime.date(value_1.year, value_1.month, value_1.day)
219
+ value_1 = datetime.date(value_1.year, value_1.month, value_1.day) if value_1 else None
222
220
  if type(value_2) == str:
223
221
  value_2 = dateparser.parse(value_2)
224
- value_2 = datetime.date(value_2.year, value_2.month, value_2.day)
222
+ value_2 = datetime.date(value_2.year, value_2.month, value_2.day) if value_2 else None
225
223
 
226
224
  # two times can be the same but if one is datetime-aware and one is not, python will treat them as not equal.
227
225
  # we want to treat such times as being the same. Therefore, check for equality but ignore the timezone.
@@ -5,16 +5,14 @@ from typing import TYPE_CHECKING, Any, Callable, Self, overload
5
5
 
6
6
  import dateparser # type: ignore
7
7
 
8
- import clearskies.decorators
9
- import clearskies.typing
10
- from clearskies import configs
8
+ from clearskies import configs, decorators
11
9
  from clearskies.autodoc.schema import Datetime as AutoDocDatetime
12
- from clearskies.autodoc.schema import Schema as AutoDocSchema
13
10
  from clearskies.column import Column
14
- from clearskies.query import Condition
15
11
 
16
12
  if TYPE_CHECKING:
17
- from clearskies import Model
13
+ from clearskies import Model, typing
14
+ from clearskies.autodoc.schema import Schema as AutoDocSchema
15
+ from clearskies.query import Condition
18
16
 
19
17
 
20
18
  class Datetime(Column):
@@ -127,7 +125,7 @@ class Datetime(Column):
127
125
  auto_doc_class: type[AutoDocSchema] = AutoDocDatetime
128
126
  _descriptor_config_map = None
129
127
 
130
- @clearskies.decorators.parameters_to_properties
128
+ @decorators.parameters_to_properties
131
129
  def __init__(
132
130
  self,
133
131
  date_format: str = "%Y-%m-%d %H:%M:%S",
@@ -140,10 +138,10 @@ class Datetime(Column):
140
138
  is_writeable: bool = True,
141
139
  is_searchable: bool = True,
142
140
  is_temporary: bool = False,
143
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
144
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
145
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
146
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
141
+ validators: typing.validator | list[typing.validator] = [],
142
+ on_change_pre_save: typing.action | list[typing.action] = [],
143
+ on_change_post_save: typing.action | list[typing.action] = [],
144
+ on_change_save_finished: typing.action | list[typing.action] = [],
147
145
  created_by_source_type: str = "",
148
146
  created_by_source_key: str = "",
149
147
  created_by_source_strict: bool = True,
@@ -184,7 +182,7 @@ class Datetime(Column):
184
182
  self.name: value.strftime(self.date_format),
185
183
  }
186
184
 
187
- def to_json(self, model: clearskies.model.Model) -> dict[str, Any]:
185
+ def to_json(self, model: Model) -> dict[str, Any]:
188
186
  """Grabs the column out of the model and converts it into a representation that can be turned into JSON."""
189
187
  value = self.__get__(model, model.__class__)
190
188
  if value and (isinstance(value, datetime.datetime) or isinstance(value, datetime.date)):
@@ -242,13 +240,13 @@ class Datetime(Column):
242
240
  return "date is missing timezone information"
243
241
  return ""
244
242
 
245
- def values_match(self, value_1, value_2):
243
+ def values_match(self, value_1: None | str | datetime.datetime, value_2: None | str | datetime.datetime) -> bool:
246
244
  """Compare two values to see if they are the same."""
247
245
  # in this function we deal with data directly out of the backend, so our date is likely
248
246
  # to be string-ified and we want to look for default (e.g. null) values in string form.
249
- if type(value_1) == str and ("0000-00-00" in value_1 or value_1 == self.backend_default):
247
+ if isinstance(value_1, str) and ("0000-00-00" in value_1 or value_1 == self.backend_default):
250
248
  value_1 = None
251
- if type(value_2) == str and ("0000-00-00" in value_2 or value_2 == self.backend_default):
249
+ if isinstance(value_2, str) and ("0000-00-00" in value_2 or value_2 == self.backend_default):
252
250
  value_2 = None
253
251
  number_values = 0
254
252
  if value_1:
@@ -260,11 +258,15 @@ class Datetime(Column):
260
258
  if number_values == 1:
261
259
  return False
262
260
 
263
- if type(value_1) == str:
261
+ if isinstance(value_1, str):
264
262
  value_1 = dateparser.parse(value_1)
265
- if type(value_2) == str:
263
+ if isinstance(value_2, str):
266
264
  value_2 = dateparser.parse(value_2)
267
265
 
266
+ # If neither value is a datetime, we can't compare them so they don't match.
267
+ if not isinstance(value_1, datetime.datetime) or not isinstance(value_2, datetime.datetime):
268
+ return False
269
+
268
270
  # we need to make sure we're comparing in the same timezones. For our purposes, a difference in timezone
269
271
  # is fine as long as they represent the same time (e.g. 16:00EST == 20:00UTC). For python, same time in different
270
272
  # timezones is treated as different datetime objects.
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import re
2
4
 
3
5
  from clearskies.columns.string import String
@@ -65,7 +67,7 @@ class Email(String):
65
67
  """
66
68
 
67
69
  def input_error_for_value(self, value: str, operator: str | None = None) -> str:
68
- if type(value) != str:
70
+ if not isinstance(value, str):
69
71
  return f"Value must be a string for {self.name}"
70
72
  if operator and operator.lower() == "like":
71
73
  # don't check for an email if doing a fuzzy search, since we may be searching