TypeDAL 3.9.0__tar.gz → 3.9.2__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.9.0 → typedal-3.9.2}/CHANGELOG.md +12 -0
- {typedal-3.9.0 → typedal-3.9.2}/PKG-INFO +1 -2
- {typedal-3.9.0 → typedal-3.9.2}/pyproject.toml +1 -1
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/__about__.py +1 -1
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/core.py +12 -2
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/for_py4web.py +19 -1
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_main.py +34 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_py4web.py +22 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_query_builder.py +9 -2
- {typedal-3.9.0 → typedal-3.9.2}/.github/workflows/su6.yml +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/.gitignore +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/.readthedocs.yml +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/README.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/coverage.svg +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/1_getting_started.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/2_defining_tables.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/3_building_queries.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/4_relationships.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/5_py4web.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/6_migrations.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/7_mixins.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/css/code_blocks.css +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/index.md +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/docs/requirements.txt +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/example_new.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/example_old.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/mkdocs.yml +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/__init__.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/caching.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/cli.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/config.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/fields.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/for_web2py.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/helpers.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/mixins.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/py.typed +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/serializers/as_json.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/types.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/src/typedal/web2py_py4web_shared.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/__init__.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/configs/simple.toml +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/configs/valid.env +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/configs/valid.toml +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_cli.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_config.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_docs_examples.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_helpers.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_json.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_mixins.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_mypy.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_orm.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_relationships.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_row.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_stats.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_table.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_web2py.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/test_xx_others.py +0 -0
- {typedal-3.9.0 → typedal-3.9.2}/tests/timings.py +0 -0
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
<!--next-version-placeholder-->
|
|
4
4
|
|
|
5
|
+
## v3.9.2 (2024-11-08)
|
|
6
|
+
|
|
7
|
+
### Fix
|
|
8
|
+
|
|
9
|
+
* Py4web-specific DAL now provides a singleton per db_uid, so different apps using shared typedal classes share a db instance, leading to less weird behavior (e.g. on `db.commit()`) ([`a2af3d5`](https://github.com/trialandsuccess/TypeDAL/commit/a2af3d52a3f14ddddd40ec326df9c2705ef26eca))
|
|
10
|
+
|
|
11
|
+
## v3.9.1 (2024-10-25)
|
|
12
|
+
|
|
13
|
+
### Fix
|
|
14
|
+
|
|
15
|
+
* Bool(QueryBuilder) should NOT look at the data but if any filters were applied ([`962ddf3`](https://github.com/trialandsuccess/TypeDAL/commit/962ddf37f5d1ac014b73fd6349099100cc7efb5f))
|
|
16
|
+
|
|
5
17
|
## v3.9.0 (2024-10-25)
|
|
6
18
|
|
|
7
19
|
### Feature
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: TypeDAL
|
|
3
|
-
Version: 3.9.
|
|
3
|
+
Version: 3.9.2
|
|
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
|
|
7
7
|
Project-URL: Source, https://github.com/trialandsuccess/TypeDAL
|
|
8
8
|
Author-email: Robin van der Noord <contact@trialandsuccess.nl>
|
|
9
|
-
License-Expression: MIT
|
|
10
9
|
Classifier: Development Status :: 4 - Beta
|
|
11
10
|
Classifier: Programming Language :: Python
|
|
12
11
|
Classifier: Programming Language :: Python :: 3.10
|
|
@@ -2230,9 +2230,19 @@ class QueryBuilder(typing.Generic[T_MetaInstance]):
|
|
|
2230
2230
|
|
|
2231
2231
|
def __bool__(self) -> bool:
|
|
2232
2232
|
"""
|
|
2233
|
-
Querybuilder is truthy if it has
|
|
2233
|
+
Querybuilder is truthy if it has any conditions.
|
|
2234
2234
|
"""
|
|
2235
|
-
|
|
2235
|
+
table = self.model._ensure_table_defined()
|
|
2236
|
+
default_query = typing.cast(Query, table.id > 0)
|
|
2237
|
+
return any(
|
|
2238
|
+
[
|
|
2239
|
+
self.query != default_query,
|
|
2240
|
+
self.select_args,
|
|
2241
|
+
self.select_kwargs,
|
|
2242
|
+
self.relationships,
|
|
2243
|
+
self.metadata,
|
|
2244
|
+
]
|
|
2245
|
+
)
|
|
2236
2246
|
|
|
2237
2247
|
def _extend(
|
|
2238
2248
|
self,
|
|
@@ -2,9 +2,13 @@
|
|
|
2
2
|
ONLY USE IN COMBINATION WITH PY4WEB!
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
+
import typing
|
|
6
|
+
|
|
5
7
|
import threadsafevariable
|
|
8
|
+
from configuraptor.abs import AnyType
|
|
6
9
|
from py4web.core import ICECUBE
|
|
7
10
|
from py4web.core import Fixture as _Fixture
|
|
11
|
+
from pydal.base import MetaDAL, hashlib_md5
|
|
8
12
|
|
|
9
13
|
from .core import TypeDAL
|
|
10
14
|
from .types import AnyDict
|
|
@@ -17,7 +21,21 @@ class Fixture(_Fixture): # type: ignore
|
|
|
17
21
|
"""
|
|
18
22
|
|
|
19
23
|
|
|
20
|
-
class
|
|
24
|
+
class PY4WEB_DAL_SINGLETON(MetaDAL):
|
|
25
|
+
_instances: typing.ClassVar[typing.MutableMapping[str, AnyType]] = {}
|
|
26
|
+
|
|
27
|
+
def __call__(cls, uri: str, *args: typing.Any, **kwargs: typing.Any) -> AnyType:
|
|
28
|
+
db_uid = kwargs.get("db_uid", hashlib_md5(repr(uri)).hexdigest())
|
|
29
|
+
if db_uid not in cls._instances:
|
|
30
|
+
cls._instances[db_uid] = super().__call__(*args, **kwargs)
|
|
31
|
+
|
|
32
|
+
return cls._instances[db_uid]
|
|
33
|
+
|
|
34
|
+
def _clear(cls) -> None:
|
|
35
|
+
cls._instances.clear()
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class DAL(TypeDAL, Fixture, metaclass=PY4WEB_DAL_SINGLETON): # pragma: no cover
|
|
21
39
|
"""
|
|
22
40
|
Fixture similar to the py4web pydal fixture, but for typedal.
|
|
23
41
|
"""
|
|
@@ -414,6 +414,23 @@ def test_hooks(capsys):
|
|
|
414
414
|
assert "before delete" in captured.out
|
|
415
415
|
assert "after delete" in captured.out
|
|
416
416
|
|
|
417
|
+
idx = db.hooked_table.insert(name="Steve 2")
|
|
418
|
+
steve2 = db.hooked_table(idx)
|
|
419
|
+
captured = capsys.readouterr()
|
|
420
|
+
|
|
421
|
+
assert "before insert" in captured.out
|
|
422
|
+
assert "after insert 2" in captured.out
|
|
423
|
+
|
|
424
|
+
steve2.update_record(name="Not Steve")
|
|
425
|
+
captured = capsys.readouterr()
|
|
426
|
+
assert "before update" in captured.out
|
|
427
|
+
assert "after update" in captured.out
|
|
428
|
+
|
|
429
|
+
steve2.delete_record()
|
|
430
|
+
captured = capsys.readouterr()
|
|
431
|
+
assert "before delete" in captured.out
|
|
432
|
+
assert "after delete" in captured.out
|
|
433
|
+
|
|
417
434
|
|
|
418
435
|
def test_hooks_v2(capsys):
|
|
419
436
|
@db.define()
|
|
@@ -445,6 +462,23 @@ def test_hooks_v2(capsys):
|
|
|
445
462
|
assert "before delete" in captured.out
|
|
446
463
|
assert "after delete" in captured.out
|
|
447
464
|
|
|
465
|
+
idx = db.hooked_table_v2.insert(name="Steve 2")
|
|
466
|
+
steve2 = db.hooked_table_v2(idx)
|
|
467
|
+
captured = capsys.readouterr()
|
|
468
|
+
|
|
469
|
+
assert "before insert" in captured.out
|
|
470
|
+
assert "after insert 2" in captured.out
|
|
471
|
+
|
|
472
|
+
steve2.update_record(name="Not Steve")
|
|
473
|
+
captured = capsys.readouterr()
|
|
474
|
+
assert "before update" in captured.out
|
|
475
|
+
assert "after update" in captured.out
|
|
476
|
+
|
|
477
|
+
steve2.delete_record()
|
|
478
|
+
captured = capsys.readouterr()
|
|
479
|
+
assert "before delete" in captured.out
|
|
480
|
+
assert "after delete" in captured.out
|
|
481
|
+
|
|
448
482
|
|
|
449
483
|
def test_try():
|
|
450
484
|
class SomeTableToRetry(TypedTable):
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import tempfile
|
|
3
|
+
from contextlib import chdir
|
|
2
4
|
|
|
3
5
|
from pydal.validators import IS_EMAIL, IS_NOT_IN_DB
|
|
4
6
|
|
|
@@ -44,3 +46,23 @@ def test_auth_user():
|
|
|
44
46
|
|
|
45
47
|
assert isinstance(requirements[0], IS_EMAIL)
|
|
46
48
|
assert isinstance(requirements[1], IS_NOT_IN_DB)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_py4web_dal_singleton():
|
|
52
|
+
with tempfile.TemporaryDirectory() as d:
|
|
53
|
+
with chdir(d):
|
|
54
|
+
# note: typedal caching is disabled here because otherwise the cache table might send logs to {d}/log.sql
|
|
55
|
+
# which can lead to problems in other tests :(
|
|
56
|
+
db_1a = DAL("sqlite:memory", enable_typedal_caching=False)
|
|
57
|
+
db_1b = DAL("sqlite:memory", enable_typedal_caching=False)
|
|
58
|
+
|
|
59
|
+
db_2a = DAL("sqlite://test_py4web_dal_singleton", folder=d, enable_typedal_caching=False)
|
|
60
|
+
db_2b = DAL("sqlite://test_py4web_dal_singleton", folder=d, enable_typedal_caching=False)
|
|
61
|
+
|
|
62
|
+
assert db_1a is db_1b
|
|
63
|
+
assert db_2a is db_2b
|
|
64
|
+
assert db_1a is not db_2a
|
|
65
|
+
assert db_1b is not db_2b
|
|
66
|
+
|
|
67
|
+
# reset singletons for later use:
|
|
68
|
+
DAL._clear()
|
|
@@ -401,8 +401,15 @@ def test_complex_join():
|
|
|
401
401
|
|
|
402
402
|
def test_reprs_and_bool():
|
|
403
403
|
_setup_data()
|
|
404
|
-
|
|
405
|
-
|
|
404
|
+
|
|
405
|
+
# NOTE: This logic changed: any 'empty' query table is False, and adding any conditions make it True.
|
|
406
|
+
empty = TestQueryTable.where()
|
|
407
|
+
notempty = TestQueryTable.where(id=1)
|
|
408
|
+
assert (empty or notempty) is notempty
|
|
409
|
+
assert (notempty or empty) is notempty
|
|
410
|
+
assert not empty
|
|
411
|
+
assert notempty
|
|
412
|
+
assert TestQueryTable.where(id=10000000000)
|
|
406
413
|
|
|
407
414
|
assert repr(TestQueryTable.where(id=1))
|
|
408
415
|
assert str(TestQueryTable.where(id=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
|