TypeDAL 3.12.1__py3-none-any.whl → 4.2.0__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.
typedal/mixins.py CHANGED
@@ -5,26 +5,22 @@ Mixins can add reusable fields and behavior (optimally both, otherwise it doesn'
5
5
  """
6
6
 
7
7
  import base64
8
+ import datetime as dt
8
9
  import os
9
- import typing
10
+ import typing as t
10
11
  import warnings
11
- from datetime import datetime
12
- from typing import Any, Optional
13
12
 
14
13
  from pydal import DAL
15
14
  from pydal.validators import IS_NOT_IN_DB, ValidationError
16
15
  from slugify import slugify
17
16
 
18
- from .core import ( # noqa F401 - used by example in docstring
19
- QueryBuilder,
20
- T_MetaInstance,
21
- TableMeta,
22
- TypeDAL,
23
- TypedTable,
24
- _TypedTable,
25
- )
17
+ from .core import TypeDAL
26
18
  from .fields import DatetimeField, StringField
27
- from .types import OpRow, Set
19
+ from .tables import _TypedTable
20
+ from .types import OpRow, Set, T_MetaInstance
21
+
22
+ if t.TYPE_CHECKING:
23
+ from .tables import TypedTable # noqa: F401
28
24
 
29
25
 
30
26
  class Mixin(_TypedTable):
@@ -38,9 +34,9 @@ class Mixin(_TypedTable):
38
34
  ('inconsistent method resolution' or 'metaclass conflicts')
39
35
  """
40
36
 
41
- __settings__: typing.ClassVar[dict[str, Any]]
37
+ __settings__: t.ClassVar[dict[str, t.Any]]
42
38
 
43
- def __init_subclass__(cls, **kwargs: Any):
39
+ def __init_subclass__(cls, **kwargs: t.Any):
44
40
  """
45
41
  Ensures __settings__ exists for other mixins.
46
42
  """
@@ -52,8 +48,8 @@ class TimestampsMixin(Mixin):
52
48
  A Mixin class for adding timestamp fields to a model.
53
49
  """
54
50
 
55
- created_at = DatetimeField(default=datetime.now, writable=False)
56
- updated_at = DatetimeField(default=datetime.now, writable=False)
51
+ created_at = DatetimeField(default=dt.datetime.now, writable=False)
52
+ updated_at = DatetimeField(default=dt.datetime.now, writable=False)
57
53
 
58
54
  @classmethod
59
55
  def __on_define__(cls, db: TypeDAL) -> None:
@@ -73,7 +69,7 @@ class TimestampsMixin(Mixin):
73
69
  _: Set: Unused parameter.
74
70
  row (OpRow): The row to update.
75
71
  """
76
- row["updated_at"] = datetime.now()
72
+ row["updated_at"] = dt.datetime.now()
77
73
 
78
74
  cls._before_update.append(set_updated_at)
79
75
 
@@ -89,7 +85,7 @@ def slug_random_suffix(length: int = 8) -> str:
89
85
  return base64.urlsafe_b64encode(os.urandom(length)).rstrip(b"=").decode().strip("=")
90
86
 
91
87
 
92
- T = typing.TypeVar("T")
88
+ T = t.TypeVar("T")
93
89
 
94
90
 
95
91
  # noinspection PyPep8Naming
@@ -112,7 +108,7 @@ class HAS_UNIQUE_SLUG(IS_NOT_IN_DB):
112
108
  """
113
109
  super().__init__(db, field, error_message)
114
110
 
115
- def validate(self, original: T, record_id: Optional[int] = None) -> T:
111
+ def validate(self, original: T, record_id: t.Optional[int] = None) -> T:
116
112
  """
117
113
  Performs checks to see if the slug already exists for a different row.
118
114
  """
@@ -154,7 +150,7 @@ class SlugMixin(Mixin):
154
150
  # pub:
155
151
  slug = StringField(unique=True, writable=False)
156
152
  # priv:
157
- __settings__: typing.TypedDict( # type: ignore
153
+ __settings__: t.TypedDict( # type: ignore
158
154
  "SlugFieldSettings",
159
155
  {
160
156
  "slug_field": str,
@@ -163,7 +159,11 @@ class SlugMixin(Mixin):
163
159
  ) # set via init subclass
164
160
 
165
161
  def __init_subclass__(
166
- cls, slug_field: str = None, slug_suffix_length: int = 0, slug_suffix: Optional[int] = None, **kw: Any
162
+ cls,
163
+ slug_field: t.Optional[str] = None,
164
+ slug_suffix_length: int = 0,
165
+ slug_suffix: t.Optional[int] = None,
166
+ **kw: t.Any,
167
167
  ) -> None:
168
168
  """
169
169
  Bind 'slug field' option to be used later (on_define).
@@ -176,7 +176,7 @@ class SlugMixin(Mixin):
176
176
  if slug_field is None:
177
177
  raise ValueError(
178
178
  "SlugMixin requires a valid slug_field setting: "
179
- "e.g. `class MyClass(TypedTable, SlugMixin, slug_field='title'): ...`"
179
+ "e.g. `class MyClass(TypedTable, SlugMixin, slug_field='title'): ...`",
180
180
  )
181
181
 
182
182
  if slug_suffix:
@@ -193,6 +193,10 @@ class SlugMixin(Mixin):
193
193
 
194
194
  @classmethod
195
195
  def __generate_slug_before_insert(cls, row: OpRow) -> None:
196
+ if row.get("slug"): # type: ignore
197
+ # manually set -> skip
198
+ return None
199
+
196
200
  settings = cls.__settings__
197
201
 
198
202
  text_input = row[settings["slug_field"]]
@@ -227,7 +231,7 @@ class SlugMixin(Mixin):
227
231
  slug_field.requires = current_requires
228
232
 
229
233
  @classmethod
230
- def from_slug(cls: typing.Type[T_MetaInstance], slug: str, join: bool = True) -> Optional[T_MetaInstance]:
234
+ def from_slug(cls: t.Type[T_MetaInstance], slug: str, join: bool = True) -> t.Optional[T_MetaInstance]:
231
235
  """
232
236
  Find a row by its slug.
233
237
  """
@@ -238,7 +242,7 @@ class SlugMixin(Mixin):
238
242
  return builder.first()
239
243
 
240
244
  @classmethod
241
- def from_slug_or_fail(cls: typing.Type[T_MetaInstance], slug: str, join: bool = True) -> T_MetaInstance:
245
+ def from_slug_or_fail(cls: t.Type[T_MetaInstance], slug: str, join: bool = True) -> T_MetaInstance:
242
246
  """
243
247
  Find a row by its slug, or raise an error if it doesn't exist.
244
248
  """