TypeDAL 3.11.1__tar.gz → 3.12.1__tar.gz
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-3.11.1 → typedal-3.12.1}/CHANGELOG.md +12 -0
- {typedal-3.11.1 → typedal-3.12.1}/PKG-INFO +6 -6
- {typedal-3.11.1 → typedal-3.12.1}/docs/4_relationships.md +8 -2
- {typedal-3.11.1 → typedal-3.12.1}/pyproject.toml +5 -5
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/__about__.py +1 -1
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/core.py +20 -6
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_relationships.py +5 -5
- {typedal-3.11.1 → typedal-3.12.1}/.github/workflows/su6.yml +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/.gitignore +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/.readthedocs.yml +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/README.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/coverage.svg +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/1_getting_started.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/2_defining_tables.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/3_building_queries.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/5_py4web.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/6_migrations.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/7_mixins.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/css/code_blocks.css +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/index.md +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/docs/requirements.txt +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/example_new.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/example_old.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/mkdocs.yml +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/__init__.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/caching.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/cli.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/config.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/fields.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/for_py4web.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/for_web2py.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/helpers.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/mixins.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/py.typed +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/serializers/as_json.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/types.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/src/typedal/web2py_py4web_shared.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/__init__.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/configs/simple.toml +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/configs/valid.env +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/configs/valid.toml +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_cli.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_config.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_docs_examples.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_helpers.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_json.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_main.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_mixins.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_mypy.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_orm.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_py4web.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_query_builder.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_row.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_stats.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_table.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_web2py.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/test_xx_others.py +0 -0
- {typedal-3.11.1 → typedal-3.12.1}/tests/timings.py +0 -0
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
<!--next-version-placeholder-->
|
|
4
4
|
|
|
5
|
+
## v3.12.1 (2025-04-25)
|
|
6
|
+
|
|
7
|
+
### Fix
|
|
8
|
+
|
|
9
|
+
* Support latest pydal version ([`5af1d2b`](https://github.com/trialandsuccess/TypeDAL/commit/5af1d2bbb8cd4188cfab840191816fc0de87cc4a))
|
|
10
|
+
|
|
11
|
+
## v3.12.0 (2025-04-25)
|
|
12
|
+
|
|
13
|
+
### Feature
|
|
14
|
+
|
|
15
|
+
* Support adding a `unique_alias` which improves working with multiple joins. ([`8b2112c`](https://github.com/trialandsuccess/TypeDAL/commit/8b2112cf9c97a00a9610e1af6e80e05fcc296aad))
|
|
16
|
+
|
|
5
17
|
## v3.11.1 (2025-04-25)
|
|
6
18
|
|
|
7
19
|
### Fix
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: TypeDAL
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.12.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
|
|
@@ -15,12 +15,12 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
15
15
|
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
16
16
|
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
17
17
|
Requires-Python: >=3.10
|
|
18
|
-
Requires-Dist: configurable-json
|
|
19
|
-
Requires-Dist: configuraptor
|
|
20
|
-
Requires-Dist: dill
|
|
18
|
+
Requires-Dist: configurable-json<2
|
|
19
|
+
Requires-Dist: configuraptor<2,>=1.26.2
|
|
20
|
+
Requires-Dist: dill<1
|
|
21
21
|
Requires-Dist: legacy-cgi; python_version >= '3.13'
|
|
22
|
-
Requires-Dist: pydal
|
|
23
|
-
Requires-Dist: python-slugify
|
|
22
|
+
Requires-Dist: pydal<=20250228.1
|
|
23
|
+
Requires-Dist: python-slugify<2
|
|
24
24
|
Provides-Extra: all
|
|
25
25
|
Requires-Dist: edwh-migrate[full]>=0.8.0; extra == 'all'
|
|
26
26
|
Requires-Dist: py4web; extra == 'all'
|
|
@@ -92,16 +92,22 @@ Adding the `Relationship["Sidekick"]` hint is optional, but recommended to impro
|
|
|
92
92
|
Setting up a relationship that uses a junction/pivot table is slightly harder.
|
|
93
93
|
|
|
94
94
|
```python
|
|
95
|
+
|
|
96
|
+
# with `unique_alias()` which is better if you have multiple joins:
|
|
97
|
+
|
|
95
98
|
@db.define()
|
|
96
99
|
class Post(TypedTable):
|
|
97
100
|
title: str
|
|
98
101
|
author: Author
|
|
99
102
|
|
|
100
103
|
tags = relationship(list["Tag"], on=lambda post, tag: [
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
# post and tag already have a unique alias, create one for tagged here:
|
|
105
|
+
tagged := Tagged.unique_alias(),
|
|
106
|
+
tagged.on(tagged.post == post.id),
|
|
107
|
+
tag.on(tag.id == tagged.tag),
|
|
103
108
|
])
|
|
104
109
|
|
|
110
|
+
# without unique alias:
|
|
105
111
|
|
|
106
112
|
@db.define()
|
|
107
113
|
class Tag(TypedTable):
|
|
@@ -24,11 +24,11 @@ classifiers = [
|
|
|
24
24
|
"Programming Language :: Python :: Implementation :: PyPy",
|
|
25
25
|
]
|
|
26
26
|
dependencies = [
|
|
27
|
-
"pydal
|
|
28
|
-
"dill", # caching
|
|
29
|
-
"configuraptor >= 1.26.2", # config
|
|
30
|
-
"Configurable-JSON", # json dumping
|
|
31
|
-
"python-slugify",
|
|
27
|
+
"pydal <= 20250228.1", # core
|
|
28
|
+
"dill < 1", # caching
|
|
29
|
+
"configuraptor >= 1.26.2, < 2", # config
|
|
30
|
+
"Configurable-JSON < 2", # json dumping
|
|
31
|
+
"python-slugify < 2",
|
|
32
32
|
"legacy-cgi; python_version >= '3.13'"
|
|
33
33
|
]
|
|
34
34
|
|
|
@@ -11,6 +11,7 @@ import math
|
|
|
11
11
|
import sys
|
|
12
12
|
import types
|
|
13
13
|
import typing
|
|
14
|
+
import uuid
|
|
14
15
|
import warnings
|
|
15
16
|
from collections import defaultdict
|
|
16
17
|
from copy import copy
|
|
@@ -1179,11 +1180,21 @@ class TableMeta(type):
|
|
|
1179
1180
|
Useful for joins when joining the same table multiple times.
|
|
1180
1181
|
|
|
1181
1182
|
See Also:
|
|
1182
|
-
http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer
|
|
1183
|
+
http://web2py.com/books/default/chapter/29/06/the-database-abstraction-layer#One-to-many-relation
|
|
1183
1184
|
"""
|
|
1184
1185
|
table = self._ensure_table_defined()
|
|
1185
1186
|
return typing.cast(Type[T_MetaInstance], table.with_alias(alias))
|
|
1186
1187
|
|
|
1188
|
+
def unique_alias(self: Type[T_MetaInstance]) -> Type[T_MetaInstance]:
|
|
1189
|
+
"""
|
|
1190
|
+
Generates a unique alias for this table.
|
|
1191
|
+
|
|
1192
|
+
Useful for joins when joining the same table multiple times
|
|
1193
|
+
and you don't want to keep track of aliases yourself.
|
|
1194
|
+
"""
|
|
1195
|
+
key = f"{self.__name__.lower()}_{hash(uuid.uuid4())}"
|
|
1196
|
+
return self.with_alias(key)
|
|
1197
|
+
|
|
1187
1198
|
# hooks:
|
|
1188
1199
|
def before_insert(
|
|
1189
1200
|
cls: Type[T_MetaInstance],
|
|
@@ -1270,7 +1281,7 @@ class TypedField(Expression, typing.Generic[T_Value]): # pragma: no cover
|
|
|
1270
1281
|
|
|
1271
1282
|
def __init__(
|
|
1272
1283
|
self,
|
|
1273
|
-
_type: Type[T_Value] | types.UnionType = str,
|
|
1284
|
+
_type: Type[T_Value] | types.UnionType = str, # type: ignore
|
|
1274
1285
|
/,
|
|
1275
1286
|
**settings: Unpack[FieldSettings],
|
|
1276
1287
|
) -> None:
|
|
@@ -2683,6 +2694,12 @@ class QueryBuilder(typing.Generic[T_MetaInstance]):
|
|
|
2683
2694
|
if not isinstance(on, list): # pragma: no cover
|
|
2684
2695
|
on = [on]
|
|
2685
2696
|
|
|
2697
|
+
on = [
|
|
2698
|
+
_
|
|
2699
|
+
for _ in on
|
|
2700
|
+
# only allow Expressions (query and such):
|
|
2701
|
+
if isinstance(_, pydal.objects.Expression)
|
|
2702
|
+
]
|
|
2686
2703
|
left.extend(on)
|
|
2687
2704
|
elif method == "left":
|
|
2688
2705
|
# .on not given, generate it:
|
|
@@ -2826,10 +2843,7 @@ class QueryBuilder(typing.Generic[T_MetaInstance]):
|
|
|
2826
2843
|
db = self._get_db()
|
|
2827
2844
|
query = self.__count(db, distinct=distinct)
|
|
2828
2845
|
|
|
2829
|
-
return typing.cast(
|
|
2830
|
-
str,
|
|
2831
|
-
db(query)._count(distinct)
|
|
2832
|
-
)
|
|
2846
|
+
return typing.cast(str, db(query)._count(distinct))
|
|
2833
2847
|
|
|
2834
2848
|
def exists(self) -> bool:
|
|
2835
2849
|
"""
|
|
@@ -25,10 +25,11 @@ class TaggableMixin:
|
|
|
25
25
|
list["Tag"],
|
|
26
26
|
# lambda self, _: (Tagged.entity == self.gid) & (Tagged.tag == Tag.id)
|
|
27
27
|
# doing an .on with and & inside can lead to a cross join,
|
|
28
|
-
# for relationships with pivot tables a manual on query is prefered:
|
|
29
|
-
on=lambda entity,
|
|
30
|
-
Tagged.
|
|
31
|
-
|
|
28
|
+
# for relationships with pivot tables a manual on query with aliases is prefered:
|
|
29
|
+
on=lambda entity, tag: [
|
|
30
|
+
tagged := Tagged.unique_alias(),
|
|
31
|
+
tagged.on(tagged.entity == entity.gid),
|
|
32
|
+
tag.on((tagged.tag == tag.id)),
|
|
32
33
|
],
|
|
33
34
|
)
|
|
34
35
|
# tags = relationship(list["Tag"], tagged)
|
|
@@ -186,7 +187,6 @@ def test_typedal_way():
|
|
|
186
187
|
Empty.first_or_fail()
|
|
187
188
|
|
|
188
189
|
# user through article: 1 - many
|
|
189
|
-
|
|
190
190
|
all_articles = Article.join().collect().as_dict()
|
|
191
191
|
|
|
192
192
|
assert all_articles[3]["final_editor"]["name"] == "Editor 1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|