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
@@ -1,15 +1,18 @@
1
- import inspect
1
+ from __future__ import annotations
2
+
2
3
  from functools import cmp_to_key
3
- from typing import Any, Callable
4
+ from typing import TYPE_CHECKING, Any, Callable
4
5
 
5
- import clearskies.model
6
- import clearskies.query
7
6
  from clearskies import functional
8
7
  from clearskies.autodoc.schema import Integer as AutoDocInteger
9
8
  from clearskies.autodoc.schema import Schema as AutoDocSchema
10
9
  from clearskies.backends.backend import Backend
11
10
  from clearskies.di import InjectableProperties, inject
12
11
 
12
+ if TYPE_CHECKING:
13
+ from clearskies import Model
14
+ from clearskies.query import Condition, Join, Query, Sort
15
+
13
16
 
14
17
  class Null:
15
18
  def __lt__(self, other):
@@ -31,7 +34,7 @@ def gentle_float_conversion(value):
31
34
  return value
32
35
 
33
36
 
34
- def _sort(row_a: Any, row_b: Any, sorts: list[clearskies.query.Sort], default_table_name: str) -> int:
37
+ def _sort(row_a: Any, row_b: Any, sorts: list[Sort], default_table_name: str) -> int:
35
38
  for sort in sorts:
36
39
  # so, if we've done a join then the rows will have data from all joined tables via a dict of dicts.
37
40
  # if there wasn't a join then we'll just have the data
@@ -92,7 +95,7 @@ class MemoryTable:
92
95
  _id_index: dict[int | str, int] = {}
93
96
  id_column_name: str = ""
94
97
  _next_id: int = 1
95
- _model_class: type[clearskies.model.Model] = None # type: ignore
98
+ _model_class: type[Model] = None # type: ignore
96
99
 
97
100
  # here be dragons. This is not a 100% drop-in replacement for the equivalent SQL operators
98
101
  # https://codereview.stackexchange.com/questions/259198/in-memory-table-filtering-in-python
@@ -124,7 +127,7 @@ class MemoryTable:
124
127
  "in": lambda column, values, null: lambda row: row.get(column, null) in values,
125
128
  }
126
129
 
127
- def __init__(self, model_class: type[clearskies.model.Model]) -> None:
130
+ def __init__(self, model_class: type[Model]) -> None:
128
131
  self._rows = []
129
132
  self._id_index = {}
130
133
  self.id_column_name = model_class.id_column_name
@@ -193,13 +196,13 @@ class MemoryTable:
193
196
  self._rows[index] = None
194
197
  return True
195
198
 
196
- def count(self, query: clearskies.query.Query):
199
+ def count(self, query: Query):
197
200
  return len(self.rows(query, query.conditions, filter_only=True))
198
201
 
199
202
  def rows(
200
203
  self,
201
- query: clearskies.query.Query,
202
- conditions: list[clearskies.query.Condition],
204
+ query: Query,
205
+ conditions: list[Condition],
203
206
  filter_only: bool = False,
204
207
  next_page_data: dict[str, Any] | None = None,
205
208
  ):
@@ -232,7 +235,7 @@ class MemoryTable:
232
235
  return rows
233
236
 
234
237
  @classmethod
235
- def _condition_as_filter(cls, condition: clearskies.query.Condition) -> Callable:
238
+ def _condition_as_filter(cls, condition: Condition) -> Callable:
236
239
  column = condition.column_name
237
240
  values = condition.values
238
241
  return cls._operator_lambda_builders[condition.operator.lower()](column, values, cls.null)
@@ -469,19 +472,19 @@ class MemoryBackend(Backend, InjectableProperties):
469
472
  def silent_on_missing_tables(self, silent=True):
470
473
  self._silent_on_missing_tables = silent
471
474
 
472
- def create_table(self, model_class: type[clearskies.model.Model]):
475
+ def create_table(self, model_class: type[Model]):
473
476
  self.load_default_data()
474
477
  table_name = model_class.destination_name()
475
478
  if table_name in self.__class__._tables:
476
479
  return
477
480
  self.__class__._tables[table_name] = MemoryTable(model_class)
478
481
 
479
- def has_table(self, model_class: type[clearskies.model.Model]) -> bool:
482
+ def has_table(self, model_class: type[Model]) -> bool:
480
483
  self.load_default_data()
481
484
  table_name = model_class.destination_name()
482
485
  return table_name in self.__class__._tables
483
486
 
484
- def get_table(self, model_class: type[clearskies.model.Model], create_if_missing=False) -> MemoryTable:
487
+ def get_table(self, model_class: type[Model], create_if_missing=False) -> MemoryTable:
485
488
  table_name = model_class.destination_name()
486
489
  if table_name not in self.__class__._tables:
487
490
  if create_if_missing:
@@ -492,25 +495,23 @@ class MemoryBackend(Backend, InjectableProperties):
492
495
  )
493
496
  return self.__class__._tables[table_name]
494
497
 
495
- def create_with_model_class(
496
- self, data: dict[str, Any], model_class: type[clearskies.model.Model]
497
- ) -> dict[str, Any]:
498
+ def create_with_model_class(self, data: dict[str, Any], model_class: type[Model]) -> dict[str, Any]:
498
499
  self.create_table(model_class)
499
500
  return self.get_table(model_class).create(data)
500
501
 
501
- def update(self, id: int | str, data: dict[str, Any], model: clearskies.model.Model) -> dict[str, Any]:
502
+ def update(self, id: int | str, data: dict[str, Any], model: Model) -> dict[str, Any]:
502
503
  self.create_table(model.__class__)
503
504
  return self.get_table(model.__class__).update(id, data)
504
505
 
505
- def create(self, data: dict[str, Any], model: clearskies.model.Model) -> dict[str, Any]:
506
+ def create(self, data: dict[str, Any], model: Model) -> dict[str, Any]:
506
507
  self.create_table(model.__class__)
507
508
  return self.get_table(model.__class__).create(data)
508
509
 
509
- def delete(self, id: int | str, model: clearskies.model.Model) -> bool:
510
+ def delete(self, id: int | str, model: Model) -> bool:
510
511
  self.create_table(model.__class__)
511
512
  return self.get_table(model.__class__).delete(id)
512
513
 
513
- def count(self, query: clearskies.query.Query) -> int:
514
+ def count(self, query: Query) -> int:
514
515
  self.check_query(query)
515
516
  if not self.has_table(query.model_class):
516
517
  if self._silent_on_missing_tables:
@@ -528,9 +529,7 @@ class MemoryBackend(Backend, InjectableProperties):
528
529
  query.joins = [join for join in query.joins if join.join_type != "LEFT"]
529
530
  return len(self.rows_with_joins(query))
530
531
 
531
- def records(
532
- self, query: clearskies.query.Query, next_page_data: dict[str, str | int] | None = None
533
- ) -> list[dict[str, Any]]:
532
+ def records(self, query: Query, next_page_data: dict[str, str | int] | None = None) -> list[dict[str, Any]]:
534
533
  self.check_query(query)
535
534
  if not self.has_table(query.model_class):
536
535
  if self._silent_on_missing_tables:
@@ -568,7 +567,7 @@ class MemoryBackend(Backend, InjectableProperties):
568
567
  next_page_data["start"] = start + query.limit
569
568
  return rows
570
569
 
571
- def rows_with_joins(self, query: clearskies.query.Query) -> list[dict[str, Any]]:
570
+ def rows_with_joins(self, query: Query) -> list[dict[str, Any]]:
572
571
  joins = [*query.joins]
573
572
  conditions = [*query.conditions]
574
573
  # quick sanity check
@@ -642,15 +641,13 @@ class MemoryBackend(Backend, InjectableProperties):
642
641
  raise ValueError(f"Cannot return rows for unknown table '{table_name}'")
643
642
  return list(filter(None, self.__class__._tables[table_name]._rows))
644
643
 
645
- def check_query(self, query: clearskies.query.Query) -> None:
644
+ def check_query(self, query: Query) -> None:
646
645
  if query.group_by:
647
646
  raise KeyError(
648
647
  f"MemoryBackend does not support group_by clauses in queries. You may be using the wrong backend."
649
648
  )
650
649
 
651
- def conditions_for_table(
652
- self, table_name: str, conditions: list[clearskies.query.Condition], is_left=False
653
- ) -> list[clearskies.query.Condition]:
650
+ def conditions_for_table(self, table_name: str, conditions: list[Condition], is_left=False) -> list[Condition]:
654
651
  """
655
652
  Return only the conditions for the given table.
656
653
 
@@ -667,7 +664,7 @@ class MemoryBackend(Backend, InjectableProperties):
667
664
  self,
668
665
  rows: list[dict[str, Any]],
669
666
  join_rows: list[dict[str, Any]],
670
- join: clearskies.query.Join,
667
+ join: Join,
671
668
  joined_tables: list[str],
672
669
  ) -> list[dict[str, Any]]:
673
670
  """
@@ -1,12 +1,13 @@
1
- from typing import Any, Callable
1
+ from typing import TYPE_CHECKING, Any, Callable
2
2
 
3
- import clearskies
4
- from clearskies.autodoc.schema import Integer as AutoDocInteger
5
3
  from clearskies.autodoc.schema import Schema as AutoDocSchema
6
- from clearskies.autodoc.schema import String as AutoDocString
7
4
  from clearskies.backends.backend import Backend
8
- from clearskies.di import InjectableProperties, inject
9
- from clearskies.functional import routing, string
5
+ from clearskies.di import inject
6
+ from clearskies.query import Condition, Query
7
+
8
+ if TYPE_CHECKING:
9
+ from clearskies import Model
10
+ from clearskies.authentication import Authentication
10
11
 
11
12
 
12
13
  class SecretsBackend(Backend):
@@ -31,11 +32,11 @@ class SecretsBackend(Backend):
31
32
  def __init__(self):
32
33
  pass
33
34
 
34
- def check_query(self, query: clearskies.query.Query) -> None:
35
+ def check_query(self, query: Query) -> None:
35
36
  if not query.conditions:
36
37
  raise KeyError(f"You must search by an id when using the secrets backend.")
37
38
 
38
- def update(self, id: str, data: dict[str, Any], model: clearskies.model.Model) -> dict[str, Any]: # type: ignore[override]
39
+ def update(self, id: str, data: dict[str, Any], model: Model) -> dict[str, Any]: # type: ignore[override]
39
40
  """Update the record with the given id with the information from the data dictionary."""
40
41
  folder_path = self._make_folder_path(model, id)
41
42
  for key, value in data.items():
@@ -44,20 +45,16 @@ class SecretsBackend(Backend):
44
45
  self.secrets.update(f"{folder_path}{key}", value)
45
46
 
46
47
  # and now query again to fetch the updated record.
47
- return self.records(
48
- clearskies.query.Query(
49
- model.__class__, conditions=[clearskies.query.Condition(f"{model.id_column_name}={id}")]
50
- )
51
- )[0]
48
+ return self.records(Query(model.__class__, conditions=[Condition(f"{model.id_column_name}={id}")]))[0]
52
49
 
53
- def create(self, data: dict[str, Any], model: clearskies.model.Model) -> dict[str, Any]:
50
+ def create(self, data: dict[str, Any], model: Model) -> dict[str, Any]:
54
51
  if not model.id_column_name in data:
55
52
  raise ValueError(
56
53
  f"You must provide '{model.id_column_name}' when creating a record with the secrets backend"
57
54
  )
58
55
  return self.update(data[model.id_column_name], data, model)
59
56
 
60
- def delete(self, id: str, model: clearskies.model.Model) -> bool: # type: ignore[override]
57
+ def delete(self, id: str, model: Model) -> bool: # type: ignore[override]
61
58
  """
62
59
  Delete the record with the given id.
63
60
 
@@ -65,9 +62,7 @@ class SecretsBackend(Backend):
65
62
  """
66
63
  return True
67
64
 
68
- def records(
69
- self, query: clearskies.query.Query, next_page_data: dict[str, str | int] | None = None
70
- ) -> list[dict[str, Any]]:
65
+ def records(self, query: Query, next_page_data: dict[str, str | int] | None = None) -> list[dict[str, Any]]:
71
66
  """Return a list of records that match the given query configuration."""
72
67
  self.check_query(query)
73
68
  for condition in query.conditions:
clearskies/column.py CHANGED
@@ -1,30 +1,22 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any, Callable, Self, Type, overload
4
-
5
- import clearskies.configs.actions
6
- import clearskies.configs.boolean
7
- import clearskies.configs.select
8
- import clearskies.configs.string
9
- import clearskies.configs.string_or_callable
10
- import clearskies.configs.validators
11
- import clearskies.configurable
12
- import clearskies.decorators
13
- import clearskies.di
14
- import clearskies.model
15
- import clearskies.typing
16
- from clearskies.autodoc.schema import Schema as AutoDocSchema
3
+ from typing import TYPE_CHECKING, Any, Callable, Self, overload
4
+
5
+ from clearskies import configs, configurable, decorators
17
6
  from clearskies.autodoc.schema import String as AutoDocString
18
- from clearskies.query.condition import Condition, ParsedCondition
7
+ from clearskies.di import InjectableProperties, inject
8
+ from clearskies.query.condition import ParsedCondition
19
9
  from clearskies.validator import Validator
20
10
 
21
11
  if TYPE_CHECKING:
22
- from clearskies import Model, Schema
12
+ from clearskies import Model, Schema, typing
13
+ from clearskies.autodoc.schema import Schema as AutoDocSchema
14
+ from clearskies.query.condition import Condition
23
15
 
24
16
 
25
- class Column(clearskies.configurable.Configurable, clearskies.di.InjectableProperties):
17
+ class Column(configurable.Configurable, InjectableProperties):
26
18
  """
27
- Columns are used to build schemes and enable a variety of levels of automation with clearskies.
19
+ Columns are used to build schemes and enable a variety of levels of automation with.
28
20
 
29
21
  Columns are used to define your schemas in clearskies, especially via models. The column definitions are then used by endpoints
30
22
  and other aspects of the clearskies framework to automate things like input validation, front-end/backend-transformations, and more.
@@ -33,7 +25,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
33
25
  """
34
26
  The column class gets the full DI container, because it does a lot of object building itself
35
27
  """
36
- di = clearskies.di.inject.Di()
28
+ di = inject.Di()
37
29
 
38
30
  """
39
31
  A default value to set for this column.
@@ -79,7 +71,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
79
71
  }
80
72
  ```
81
73
  """
82
- default = clearskies.configs.string.String(default=None)
74
+ default = configs.string.String(default=None)
83
75
 
84
76
  """
85
77
  A value to set for this column during a save operation.
@@ -143,7 +135,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
143
135
  e.g., `date_of_birth` is `age` years behind the current time (as recorded in the `created` timestamp).
144
136
 
145
137
  """
146
- setable = clearskies.configs.string_or_callable.StringOrCallable(default=None)
138
+ setable = configs.string_or_callable.StringOrCallable(default=None)
147
139
 
148
140
  """
149
141
  Whether or not this column can be converted to JSON and included in an API response.
@@ -151,7 +143,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
151
143
  If this is set to False for a column and you attempt to set that column as a readable_column in an endpoint,
152
144
  clearskies will throw an exception.
153
145
  """
154
- is_readable = clearskies.configs.boolean.Boolean(default=True)
146
+ is_readable = configs.boolean.Boolean(default=True)
155
147
 
156
148
  """
157
149
  Whether or not this column can be set via an API call.
@@ -159,7 +151,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
159
151
  If this is set to False for a column and you attempt to set the column as a writeable column in an endpoint,
160
152
  clearskies will throw an exception.
161
153
  """
162
- is_writeable = clearskies.configs.boolean.Boolean(default=True)
154
+ is_writeable = configs.boolean.Boolean(default=True)
163
155
 
164
156
  """
165
157
  Whether or not it is possible to search by this column
@@ -167,7 +159,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
167
159
  If this is set to False for a column and you attempt to set the column as a searchable column in an endpoint,
168
160
  clearskies will throw an exception.
169
161
  """
170
- is_searchable = clearskies.configs.boolean.Boolean(default=True)
162
+ is_searchable = configs.boolean.Boolean(default=True)
171
163
 
172
164
  """
173
165
  Whether or not this column is temporary. A temporary column is not persisted to the backend.
@@ -228,7 +220,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
228
220
  If you were using an SQL database, you would not have to put a `date_of_birth` column in your table.
229
221
 
230
222
  """
231
- is_temporary = clearskies.configs.boolean.Boolean(default=False)
223
+ is_temporary = configs.boolean.Boolean(default=False)
232
224
 
233
225
  """
234
226
  Validators to use when checking the input for this column during write operations from the API.
@@ -319,7 +311,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
319
311
  }
320
312
  ```
321
313
  """
322
- validators = clearskies.configs.validators.Validators(default=[])
314
+ validators = configs.validators.Validators(default=[])
323
315
 
324
316
  """
325
317
  Actions to take during the pre-save step of the save process if the column has changed during the active save operation.
@@ -403,7 +395,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
403
395
  ```
404
396
 
405
397
  """
406
- on_change_pre_save = clearskies.configs.actions.Actions(default=[])
398
+ on_change_pre_save = configs.actions.Actions(default=[])
407
399
 
408
400
  """
409
401
  Actions to take during the post-save step of the process if the column has changed during the active save.
@@ -521,7 +513,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
521
513
  ```
522
514
 
523
515
  """
524
- on_change_post_save = clearskies.configs.actions.Actions(default=[])
516
+ on_change_post_save = configs.actions.Actions(default=[])
525
517
 
526
518
  """
527
519
  Actions to take during the save-finished step of the save process if the column has changed in the save.
@@ -538,7 +530,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
538
530
  Unlike pre_save and post_save, `data` is not provided because this data has already been merged into the
539
531
  model. If you need some context from the completed save operation, use methods like `was_changed` and `previous_value`.
540
532
  """
541
- on_change_save_finished = clearskies.configs.actions.Actions(default=[])
533
+ on_change_save_finished = configs.actions.Actions(default=[])
542
534
 
543
535
  """
544
536
  Use in conjunction with `created_by_source_type` to have this column automatically populated by data from an HTTP request.
@@ -554,7 +546,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
554
546
 
555
547
  See created_by_source_type for usage examples.
556
548
  """
557
- created_by_source_key = clearskies.configs.string.String(default="")
549
+ created_by_source_key = configs.string.String(default="")
558
550
 
559
551
  """
560
552
  Use in conjunction with `created_by_source_key` to have this column automatically populated by data from ann HTTP request.
@@ -614,20 +606,20 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
614
606
  ```
615
607
 
616
608
  """
617
- created_by_source_type = clearskies.configs.select.Select(
609
+ created_by_source_type = configs.select.Select(
618
610
  ["authorization_data", "http_header", "routing_data", ""], default=""
619
611
  )
620
612
 
621
613
  """
622
614
  If True, and the key requested via created_by_source_key doesn't exist in the designated source, an error will be raised.
623
615
  """
624
- created_by_source_strict = clearskies.configs.boolean.Boolean(default=True)
616
+ created_by_source_strict = configs.boolean.Boolean(default=True)
625
617
 
626
618
  """ The model class this column is associated with. """
627
- model_class = clearskies.configs.Schema()
619
+ model_class = configs.Schema()
628
620
 
629
621
  """ The name of this column. """
630
- name = clearskies.configs.string.String()
622
+ name = configs.string.String()
631
623
 
632
624
  """
633
625
  Simple flag to denote if the column is unique or not.
@@ -669,7 +661,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
669
661
  """
670
662
  auto_doc_class: type[AutoDocSchema] = AutoDocString
671
663
 
672
- @clearskies.decorators.parameters_to_properties
664
+ @decorators.parameters_to_properties
673
665
  def __init__(
674
666
  self,
675
667
  default: str | None = None,
@@ -678,10 +670,10 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
678
670
  is_writeable: bool = True,
679
671
  is_searchable: bool = True,
680
672
  is_temporary: bool = False,
681
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
682
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
683
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
684
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
673
+ validators: typing.validator | list[typing.validator] = [],
674
+ on_change_pre_save: typing.action | list[typing.action] = [],
675
+ on_change_post_save: typing.action | list[typing.action] = [],
676
+ on_change_save_finished: typing.action | list[typing.action] = [],
685
677
  created_by_source_type: str = "",
686
678
  created_by_source_key: str = "",
687
679
  created_by_source_strict: bool = True,
@@ -810,11 +802,11 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
810
802
  }
811
803
  return additional_write_columns
812
804
 
813
- def to_json(self, model: clearskies.model.Model) -> dict[str, Any]:
805
+ def to_json(self, model: Model) -> dict[str, Any]:
814
806
  """Grabs the column out of the model and converts it into a representation that can be turned into JSON."""
815
807
  return {self.name: self.__get__(model, model.__class__)}
816
808
 
817
- def input_errors(self, model: clearskies.model.Model, data: dict[str, Any]) -> dict[str, Any]:
809
+ def input_errors(self, model: Model, data: dict[str, Any]) -> dict[str, Any]:
818
810
  """
819
811
  Check the given dictionary of data for any possible input errors.
820
812
 
@@ -885,7 +877,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
885
877
  """
886
878
  return ""
887
879
 
888
- def pre_save(self, data: dict[str, Any], model: clearskies.model.Model) -> dict[str, Any]:
880
+ def pre_save(self, data: dict[str, Any], model: Model) -> dict[str, Any]:
889
881
  """
890
882
  Make any necessary changes to the data before starting the save process.
891
883
 
@@ -914,7 +906,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
914
906
  data = self.execute_actions_with_data(self.on_change_pre_save, model, data)
915
907
  return data
916
908
 
917
- def post_save(self, data: dict[str, Any], model: clearskies.model.Model, id: int | str) -> None:
909
+ def post_save(self, data: dict[str, Any], model: Model, id: int | str) -> None:
918
910
  """
919
911
  Make any changes needed after persisting data to the backend.
920
912
 
@@ -940,7 +932,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
940
932
  require_dict_return_value=False,
941
933
  )
942
934
 
943
- def save_finished(self, model: clearskies.model.Model) -> None:
935
+ def save_finished(self, model: Model) -> None:
944
936
  """
945
937
  Make any necessary changes needed after a save has completely finished.
946
938
 
@@ -980,8 +972,8 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
980
972
 
981
973
  def execute_actions_with_data(
982
974
  self,
983
- actions: list[clearskies.typing.action],
984
- model: clearskies.model.Model,
975
+ actions: list[typing.action],
976
+ model: Model,
985
977
  data: dict[str, Any],
986
978
  id: int | str | None = None,
987
979
  context: str = "on_change_pre_save",
@@ -1016,8 +1008,8 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
1016
1008
 
1017
1009
  def execute_actions(
1018
1010
  self,
1019
- actions: list[clearskies.typing.action],
1020
- model: clearskies.model.Model,
1011
+ actions: list[typing.action],
1012
+ model: Model,
1021
1013
  ) -> None:
1022
1014
  """Execute a given set of actions."""
1023
1015
  input_output = self.di.build("input_output", cache=True)
@@ -1036,9 +1028,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
1036
1028
  """
1037
1029
  return value_1 == value_2
1038
1030
 
1039
- def add_search(
1040
- self, model: clearskies.model.Model, value: str, operator: str = "", relationship_reference: str = ""
1041
- ) -> clearskies.model.Model:
1031
+ def add_search(self, model: Model, value: str, operator: str = "", relationship_reference: str = "") -> Model:
1042
1032
  return model.where(self.condition(operator, value))
1043
1033
 
1044
1034
  def build_condition(self, value: str, operator: str = "", column_prefix: str = ""):
@@ -1068,9 +1058,7 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
1068
1058
  """Process user data to decide if the end-user is specifying an allowed operator."""
1069
1059
  return operator.lower() in self._allowed_search_operators
1070
1060
 
1071
- def n_plus_one_add_joins(
1072
- self, model: clearskies.model.Model, column_names: list[str] = []
1073
- ) -> clearskies.model.Model:
1061
+ def n_plus_one_add_joins(self, model: Model, column_names: list[str] = []) -> Model:
1074
1062
  """Add any additional joins to solve the N+1 problem."""
1075
1063
  return model
1076
1064
 
@@ -1096,11 +1084,11 @@ class Column(clearskies.configurable.Configurable, clearskies.di.InjectablePrope
1096
1084
 
1097
1085
  def where_for_request(
1098
1086
  self,
1099
- model: clearskies.model.Model,
1087
+ model: Model,
1100
1088
  routing_data: dict[str, str],
1101
1089
  authorization_data: dict[str, Any],
1102
1090
  input_output,
1103
- ) -> clearskies.model.Model:
1091
+ ) -> Model:
1104
1092
  """
1105
1093
  Create a hook to automatically apply filtering whenever the column makes an appearance in a get/update/list/search handler.
1106
1094
 
@@ -1,13 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Any
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.column import Column
9
7
  from clearskies.columns.has_many import HasMany
10
8
 
9
+ if TYPE_CHECKING:
10
+ from clearskies import Model, typing
11
+
11
12
 
12
13
  class Audit(HasMany):
13
14
  """
@@ -66,7 +67,7 @@ class Audit(HasMany):
66
67
  _descriptor_config_map = None
67
68
  _parent_columns: dict[str, Column] | None
68
69
 
69
- @clearskies.decorators.parameters_to_properties
70
+ @decorators.parameters_to_properties
70
71
  def __init__(
71
72
  self,
72
73
  audit_model_class,
@@ -74,17 +75,17 @@ class Audit(HasMany):
74
75
  mask_columns: list[str] = [],
75
76
  foreign_column_name: str | None = None,
76
77
  readable_child_columns: list[str] = [],
77
- where: clearskies.typing.condition | list[clearskies.typing.condition] = [],
78
+ where: typing.condition | list[typing.condition] = [],
78
79
  default: str | None = None,
79
80
  is_readable: bool = True,
80
81
  is_temporary: bool = False,
81
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
82
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
83
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
82
+ on_change_pre_save: typing.action | list[typing.action] = [],
83
+ on_change_post_save: typing.action | list[typing.action] = [],
84
+ on_change_save_finished: typing.action | list[typing.action] = [],
84
85
  ):
85
86
  self.child_model_class = self.audit_model_class
86
87
 
87
- def save_finished(self, model):
88
+ def save_finished(self, model: Model):
88
89
  super().save_finished(model)
89
90
  old_data: dict[str, Any] = model._previous_data
90
91
  new_data: dict[str, Any] = model.get_raw_data()
@@ -114,8 +115,8 @@ class Audit(HasMany):
114
115
  # note that this is fairly simple logic to get started. It's not going to detect changes that happen
115
116
  # in other "tables". For instance, disconnecting a record by deleting an entry in a many-to-many relationship
116
117
  # won't be picked up by this.
117
- old_model = model.empty_model()
118
- old_model.data = old_data
118
+ old_model = model.empty()
119
+ old_model._data = old_data
119
120
  from_data: dict[str, Any] = {}
120
121
  to_data: dict[str, Any] = {}
121
122
  for column, new_value in new_data.items():
@@ -187,7 +188,7 @@ class Audit(HasMany):
187
188
  def parent_columns(self) -> dict[str, Column]:
188
189
  if self._parent_columns == None:
189
190
  self._parent_columns = self.di.build(self.model_class, cache=True).columns()
190
- return self._parent_columns
191
+ return self._parent_columns # type: ignore[return-value]
191
192
 
192
193
  def record(self, model, action, data=None, record_data=None):
193
194
  audit_data = {
@@ -1,11 +1,8 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections import OrderedDict
4
3
  from typing import TYPE_CHECKING, Any, Callable
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.autodoc.schema import Object as AutoDocObject
10
7
  from clearskies.autodoc.schema import Schema as AutoDocSchema
11
8
  from clearskies.autodoc.schema import String as AutoDocString
@@ -14,7 +11,7 @@ from clearskies.di.inject import InputOutput
14
11
  from clearskies.functional import validations
15
12
 
16
13
  if TYPE_CHECKING:
17
- from clearskies import Column, Model
14
+ from clearskies import Model, typing
18
15
 
19
16
 
20
17
  class BelongsToId(String):
@@ -144,7 +141,7 @@ class BelongsToId(String):
144
141
  import models.category_reference
145
142
 
146
143
 
147
- class Product(clearskies.model.Model):
144
+ class Product(clearskies.Model):
148
145
  id_column_name = "id"
149
146
  backend = clearskies.backends.MemoryBackend()
150
147
 
@@ -299,23 +296,23 @@ class BelongsToId(String):
299
296
  _allowed_search_operators = ["="]
300
297
  _descriptor_config_map = None
301
298
 
302
- @clearskies.decorators.parameters_to_properties
299
+ @decorators.parameters_to_properties
303
300
  def __init__(
304
301
  self,
305
302
  parent_model_class,
306
303
  readable_parent_columns: list[str] = [],
307
304
  join_type: str | None = None,
308
- where: clearskies.typing.condition | list[clearskies.typing.condition] = [],
305
+ where: typing.condition | list[typing.condition] = [],
309
306
  default: str | None = None,
310
307
  setable: str | Callable | None = None,
311
308
  is_readable: bool = True,
312
309
  is_writeable: bool = True,
313
310
  is_searchable: bool = True,
314
311
  is_temporary: bool = False,
315
- validators: clearskies.typing.validator | list[clearskies.typing.validator] = [],
316
- on_change_pre_save: clearskies.typing.action | list[clearskies.typing.action] = [],
317
- on_change_post_save: clearskies.typing.action | list[clearskies.typing.action] = [],
318
- on_change_save_finished: clearskies.typing.action | list[clearskies.typing.action] = [],
312
+ validators: typing.validator | list[typing.validator] = [],
313
+ on_change_pre_save: typing.action | list[typing.action] = [],
314
+ on_change_post_save: typing.action | list[typing.action] = [],
315
+ on_change_save_finished: typing.action | list[typing.action] = [],
319
316
  created_by_source_type: str = "",
320
317
  created_by_source_key: str = "",
321
318
  created_by_source_strict: bool = True,
@@ -441,9 +438,7 @@ class BelongsToId(String):
441
438
  )
442
439
  return self.parent_columns[relationship_reference].allowed_search_operators()
443
440
 
444
- def add_search(
445
- self, model: clearskies.model.Model, value: str, operator: str = "", relationship_reference: str = ""
446
- ) -> clearskies.model.Model:
441
+ def add_search(self, model: Model, value: str, operator: str = "", relationship_reference: str = "") -> Model:
447
442
  if not relationship_reference:
448
443
  return super().add_search(model, value, operator=operator)
449
444