TypeDAL 2.2.0__py3-none-any.whl → 2.2.1__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 TypeDAL might be problematic. Click here for more details.

typedal/__about__.py CHANGED
@@ -5,4 +5,4 @@ This file contains the Version info for this package.
5
5
  # SPDX-FileCopyrightText: 2023-present Robin van der Noord <robinvandernoord@gmail.com>
6
6
  #
7
7
  # SPDX-License-Identifier: MIT
8
- __version__ = "2.2.0"
8
+ __version__ = "2.2.1"
typedal/config.py CHANGED
@@ -3,6 +3,7 @@ TypeDAL can be configured by a combination of pyproject.toml (static), env (dyna
3
3
  """
4
4
  import os
5
5
  import typing
6
+ import warnings
6
7
  from pathlib import Path
7
8
  from typing import Any, Optional
8
9
 
@@ -154,7 +155,8 @@ def _load_toml(path: str | bool | None = True) -> tuple[str, dict[str, Any]]:
154
155
  data = tomli.load(f)
155
156
 
156
157
  return toml_path or "", typing.cast(dict[str, Any], data["tool"]["typedal"])
157
- except Exception:
158
+ except Exception as e:
159
+ warnings.warn(f"Could not load typedal config toml: {e}", source=e)
158
160
  return toml_path or "", {}
159
161
 
160
162
 
typedal/core.py CHANGED
@@ -54,6 +54,7 @@ from .types import (
54
54
  Pagination,
55
55
  Query,
56
56
  Rows,
57
+ Validator,
57
58
  _Types,
58
59
  )
59
60
 
@@ -523,6 +524,7 @@ class TypeDAL(pydal.DAL): # type: ignore
523
524
  relationships=typing.cast(dict[str, Relationship[Any]], relationships),
524
525
  )
525
526
  self._class_map[str(table)] = cls
527
+ cls.__on_define__(self)
526
528
  else:
527
529
  warnings.warn("db.define used without inheriting TypedTable. This could lead to strange problems!")
528
530
 
@@ -1165,6 +1167,8 @@ class TypedField(typing.Generic[T_Value]): # pragma: no cover
1165
1167
  _type: T_annotation
1166
1168
  kwargs: Any
1167
1169
 
1170
+ requires: Validator | typing.Iterable[Validator]
1171
+
1168
1172
  def __init__(self, _type: typing.Type[T_Value] | types.UnionType = str, /, **settings: Any) -> None: # type: ignore
1169
1173
  """
1170
1174
  A TypedFieldType should not be inited manually, but TypedField (from `fields.py`) should be used!
@@ -1381,6 +1385,15 @@ class TypedTable(metaclass=TableMeta):
1381
1385
  inst._setup_instance_methods()
1382
1386
  return inst
1383
1387
 
1388
+ @classmethod
1389
+ def __on_define__(cls, db: TypeDAL) -> None:
1390
+ """
1391
+ Method that can be implemented by tables to do an action after db.define is completed.
1392
+
1393
+ This can be useful if you need to add something like requires=IS_NOT_IN_DB(db, "table.field"),
1394
+ where you need a reference to the current database, which may not exist yet when defining the model.
1395
+ """
1396
+
1384
1397
  def __iter__(self) -> typing.Generator[Any, None, None]:
1385
1398
  """
1386
1399
  Allows looping through the columns.
typedal/for_py4web.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """
2
2
  ONLY USE IN COMBINATION WITH PY4WEB!
3
3
  """
4
+ import typing
4
5
  from datetime import datetime
5
6
  from typing import Any, Optional
6
7
 
@@ -8,8 +9,11 @@ import json_fix # noqa: F401
8
9
  import threadsafevariable
9
10
  from py4web.core import ICECUBE
10
11
  from py4web.core import Fixture as _Fixture
12
+ from pydal.validators import CRYPT, IS_EMAIL, IS_NOT_EMPTY, IS_NOT_IN_DB, IS_STRONG
11
13
 
12
- from .core import TypeDAL, TypedTable
14
+ from .core import TypeDAL, TypedField, TypedTable
15
+ from .fields import PasswordField
16
+ from .types import Validator
13
17
 
14
18
 
15
19
  class Fixture(_Fixture): # type: ignore
@@ -53,13 +57,23 @@ class AuthUser(TypedTable):
53
57
 
54
58
  # call db.define on this when ready
55
59
 
56
- email: str
57
- password: str
58
- first_name: Optional[str]
59
- last_name: Optional[str]
60
- sso_id: Optional[str]
61
- action_token: Optional[str]
62
- last_password_change: Optional[datetime]
60
+ email: TypedField[str]
61
+ password = PasswordField(requires=[IS_STRONG(entropy=45), CRYPT()])
62
+ first_name: TypedField[Optional[str]]
63
+ last_name: TypedField[Optional[str]]
64
+ sso_id: TypedField[Optional[str]]
65
+ action_token: TypedField[Optional[str]]
66
+ last_password_change: TypedField[Optional[datetime]]
67
+
63
68
  # past_passwords_hash: Optional[str]
64
69
  # username: Optional[str]
65
70
  # phone_number: Optional[str]
71
+
72
+ @classmethod
73
+ def __on_define__(cls, db: TypeDAL) -> None:
74
+ """
75
+ Add some requires= to the auth_user fields.
76
+ """
77
+ cls.email.requires = typing.cast(tuple[Validator, ...], (IS_EMAIL(), IS_NOT_IN_DB(db, "auth_user.email")))
78
+ cls.first_name.requires = IS_NOT_EMPTY()
79
+ cls.last_name.requires = IS_NOT_EMPTY()
typedal/types.py CHANGED
@@ -12,6 +12,7 @@ from pydal.objects import Field as _Field
12
12
  from pydal.objects import Query as _Query
13
13
  from pydal.objects import Rows as _Rows
14
14
  from pydal.objects import Set as _Set
15
+ from pydal.validators import Validator as _Validator
15
16
  from typing_extensions import NotRequired
16
17
 
17
18
 
@@ -71,6 +72,14 @@ class Rows(_Rows): # type: ignore
71
72
  """
72
73
 
73
74
 
75
+ class Validator(_Validator): # type: ignore
76
+ """
77
+ Pydal Validator object.
78
+
79
+ Make mypy happy.
80
+ """
81
+
82
+
74
83
  class _Types:
75
84
  """
76
85
  Internal type storage for stuff that mypy otherwise won't understand.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: TypeDAL
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Typing support for PyDAL
5
5
  Project-URL: Documentation, https://typedal.readthedocs.io/
6
6
  Project-URL: Issues, https://github.com/trialandsuccess/TypeDAL/issues
@@ -62,10 +62,13 @@ the underlying `db.define_table` pydal Tables.
62
62
  - `TypeDAL` is the replacement class for DAL that manages the code on top of DAL.
63
63
  - `TypedTable` must be the parent class of any custom Tables you define (e.g. `class SomeTable(TypedTable)`)
64
64
  - `TypedField` can be used instead of Python native types when extra settings (such as `default`) are required (
65
- e.g. `name = TypedField(str, default="John Doe")`). It can also be used in an annotation (`name: TypedField[str]`) to improve
65
+ e.g. `name = TypedField(str, default="John Doe")`). It can also be used in an annotation (`name: TypedField[str]`) to
66
+ improve
66
67
  editor support over only annotating with `str`.
67
- - `TypedRows`: can be used as the return type annotation of pydal's `.select()` and subscribed with the actual table class, so
68
- e.g. `rows: TypedRows[SomeTable] = db(...).select()`. When using the QueryBuilder, a `TypedRows` instance is returned by `.collect()`.
68
+ - `TypedRows`: can be used as the return type annotation of pydal's `.select()` and subscribed with the actual table
69
+ class, so
70
+ e.g. `rows: TypedRows[SomeTable] = db(...).select()`. When using the QueryBuilder, a `TypedRows` instance is returned
71
+ by `.collect()`.
69
72
 
70
73
  Version 2.0 also introduces more ORM-like funcionality.
71
74
  Most notably, a Typed Query Builder that sees your table classes as models with relationships to each other.
@@ -75,7 +78,7 @@ details.
75
78
  ## Quick Overview
76
79
 
77
80
  Below you'll find a quick overview of translation from pydal to TypeDAL. For more info,
78
- see [the docs](https://github.com/trialandsuccess/TypeDAL/tree/master/docs).
81
+ see [the docs](https://typedal.readthedocs.io/en/latest/).
79
82
 
80
83
  ### Translations from pydal to typedal
81
84
 
@@ -254,16 +257,6 @@ row: TableName = db.table_name(id=1)
254
257
 
255
258
  See [2. Defining Tables](docs/2_defining_tables.md)
256
259
 
257
- ## Roadmap
258
-
259
- This section contains a non-exhaustive list of planned features for future feature releases:
260
-
261
- - 2.2
262
- - Migrations: currently, you can use pydal's automatic migrations or disable those and manage them yourself, but
263
- adding something like [`edwh-migrate`](https://github.com/educationwarehouse/migrate#readme)
264
- with [`pydal2sql`](https://github.com/robinvandernoord/pydal2sql-core) as an option could make this project more
265
- production-friendly.
266
-
267
260
  ## Caveats
268
261
 
269
262
  - This package depends heavily on the current implementation of annotations (which are computed when the class is
@@ -0,0 +1,15 @@
1
+ typedal/__about__.py,sha256=h_6wVhT5zBpkimIzSHhAe8DZCR_Nn-sqaS8GZXghPko,206
2
+ typedal/__init__.py,sha256=QQpLiVl9w9hm2LBxey49Y_tCF_VB2bScVaS_mCjYy54,366
3
+ typedal/caching.py,sha256=53WU5J_yRLygkKoDfD0rV_dkh5oqqT--64R9Mvz050Y,7457
4
+ typedal/cli.py,sha256=MF2bGwL4SOaIqGzr1JRSvGD6CSujy88hKGgVIehlFNk,11789
5
+ typedal/config.py,sha256=9ORQqJJ_3tDmFiL2Py_9PiceXLihpMR69t6OKZ_qpe8,8387
6
+ typedal/core.py,sha256=LV0Fszbmh0pojAiARD1GKj5ooxakJmmj_4ebpvZZkcs,93644
7
+ typedal/fields.py,sha256=z2PD9vLWqBR_zXtiY0DthqTG4AeF3yxKoeuVfGXnSdg,5197
8
+ typedal/for_py4web.py,sha256=kw44_55-dBWlYmepB7YEev5sj7tbYcgzvp-Ecc7K9_I,2230
9
+ typedal/helpers.py,sha256=ZpHdwBMSANw-P9I5gs56Vf6GUbxGzFsIwbBvASKXX8s,6487
10
+ typedal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ typedal/types.py,sha256=5qm3PgS8DXGCu9ZTUWQiIi2XXD8gz4_4Csg_vZlu_yo,3379
12
+ typedal-2.2.1.dist-info/METADATA,sha256=-4kp0PN1msDhP9C07HqMh_4VCigOu0AhkN6yNrRPDkM,7623
13
+ typedal-2.2.1.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
14
+ typedal-2.2.1.dist-info/entry_points.txt,sha256=m1wqcc_10rHWPdlQ71zEkmJDADUAnZtn7Jac_6mbyUc,44
15
+ typedal-2.2.1.dist-info/RECORD,,
@@ -1,15 +0,0 @@
1
- typedal/__about__.py,sha256=8gi3xn87HBaC4npgYYvbwLigw3OR5OW7Ke_VUmHuQow,206
2
- typedal/__init__.py,sha256=QQpLiVl9w9hm2LBxey49Y_tCF_VB2bScVaS_mCjYy54,366
3
- typedal/caching.py,sha256=53WU5J_yRLygkKoDfD0rV_dkh5oqqT--64R9Mvz050Y,7457
4
- typedal/cli.py,sha256=MF2bGwL4SOaIqGzr1JRSvGD6CSujy88hKGgVIehlFNk,11789
5
- typedal/config.py,sha256=zOINxqyZ9QczzlAuPqCVqeFWq94NUiBnVQ2H89FUIWY,8290
6
- typedal/core.py,sha256=8g8IT3o7DQdNk_uTdjW56CTFRbFddKje6XBgpXTJMxM,93140
7
- typedal/fields.py,sha256=z2PD9vLWqBR_zXtiY0DthqTG4AeF3yxKoeuVfGXnSdg,5197
8
- typedal/for_py4web.py,sha256=Y7ceKEkqAThNtyO1rdP1hYZc51o4T4ZUpbkTgiCStQU,1575
9
- typedal/helpers.py,sha256=ZpHdwBMSANw-P9I5gs56Vf6GUbxGzFsIwbBvASKXX8s,6487
10
- typedal/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- typedal/types.py,sha256=lIUc826lN59_eKKojmFyhQI2auJwdzJSZ2fNbLl5D0U,3213
12
- typedal-2.2.0.dist-info/METADATA,sha256=tW3APEybDas5z-1Mb37DO0xkwXVXfAIVQXxVbuUISnA,8110
13
- typedal-2.2.0.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
14
- typedal-2.2.0.dist-info/entry_points.txt,sha256=m1wqcc_10rHWPdlQ71zEkmJDADUAnZtn7Jac_6mbyUc,44
15
- typedal-2.2.0.dist-info/RECORD,,