TypeDAL 3.9.1__tar.gz → 3.9.3__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.

Files changed (59) hide show
  1. {typedal-3.9.1 → typedal-3.9.3}/CHANGELOG.md +12 -0
  2. {typedal-3.9.1 → typedal-3.9.3}/PKG-INFO +1 -2
  3. {typedal-3.9.1 → typedal-3.9.3}/pyproject.toml +1 -1
  4. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/__about__.py +1 -1
  5. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/for_py4web.py +19 -1
  6. {typedal-3.9.1 → typedal-3.9.3}/tests/test_main.py +34 -0
  7. typedal-3.9.3/tests/test_py4web.py +79 -0
  8. typedal-3.9.1/tests/test_py4web.py +0 -46
  9. {typedal-3.9.1 → typedal-3.9.3}/.github/workflows/su6.yml +0 -0
  10. {typedal-3.9.1 → typedal-3.9.3}/.gitignore +0 -0
  11. {typedal-3.9.1 → typedal-3.9.3}/.readthedocs.yml +0 -0
  12. {typedal-3.9.1 → typedal-3.9.3}/README.md +0 -0
  13. {typedal-3.9.1 → typedal-3.9.3}/coverage.svg +0 -0
  14. {typedal-3.9.1 → typedal-3.9.3}/docs/1_getting_started.md +0 -0
  15. {typedal-3.9.1 → typedal-3.9.3}/docs/2_defining_tables.md +0 -0
  16. {typedal-3.9.1 → typedal-3.9.3}/docs/3_building_queries.md +0 -0
  17. {typedal-3.9.1 → typedal-3.9.3}/docs/4_relationships.md +0 -0
  18. {typedal-3.9.1 → typedal-3.9.3}/docs/5_py4web.md +0 -0
  19. {typedal-3.9.1 → typedal-3.9.3}/docs/6_migrations.md +0 -0
  20. {typedal-3.9.1 → typedal-3.9.3}/docs/7_mixins.md +0 -0
  21. {typedal-3.9.1 → typedal-3.9.3}/docs/css/code_blocks.css +0 -0
  22. {typedal-3.9.1 → typedal-3.9.3}/docs/index.md +0 -0
  23. {typedal-3.9.1 → typedal-3.9.3}/docs/requirements.txt +0 -0
  24. {typedal-3.9.1 → typedal-3.9.3}/example_new.py +0 -0
  25. {typedal-3.9.1 → typedal-3.9.3}/example_old.py +0 -0
  26. {typedal-3.9.1 → typedal-3.9.3}/mkdocs.yml +0 -0
  27. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/__init__.py +0 -0
  28. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/caching.py +0 -0
  29. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/cli.py +0 -0
  30. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/config.py +0 -0
  31. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/core.py +0 -0
  32. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/fields.py +0 -0
  33. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/for_web2py.py +0 -0
  34. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/helpers.py +0 -0
  35. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/mixins.py +0 -0
  36. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/py.typed +0 -0
  37. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/serializers/as_json.py +0 -0
  38. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/types.py +0 -0
  39. {typedal-3.9.1 → typedal-3.9.3}/src/typedal/web2py_py4web_shared.py +0 -0
  40. {typedal-3.9.1 → typedal-3.9.3}/tests/__init__.py +0 -0
  41. {typedal-3.9.1 → typedal-3.9.3}/tests/configs/simple.toml +0 -0
  42. {typedal-3.9.1 → typedal-3.9.3}/tests/configs/valid.env +0 -0
  43. {typedal-3.9.1 → typedal-3.9.3}/tests/configs/valid.toml +0 -0
  44. {typedal-3.9.1 → typedal-3.9.3}/tests/test_cli.py +0 -0
  45. {typedal-3.9.1 → typedal-3.9.3}/tests/test_config.py +0 -0
  46. {typedal-3.9.1 → typedal-3.9.3}/tests/test_docs_examples.py +0 -0
  47. {typedal-3.9.1 → typedal-3.9.3}/tests/test_helpers.py +0 -0
  48. {typedal-3.9.1 → typedal-3.9.3}/tests/test_json.py +0 -0
  49. {typedal-3.9.1 → typedal-3.9.3}/tests/test_mixins.py +0 -0
  50. {typedal-3.9.1 → typedal-3.9.3}/tests/test_mypy.py +0 -0
  51. {typedal-3.9.1 → typedal-3.9.3}/tests/test_orm.py +0 -0
  52. {typedal-3.9.1 → typedal-3.9.3}/tests/test_query_builder.py +0 -0
  53. {typedal-3.9.1 → typedal-3.9.3}/tests/test_relationships.py +0 -0
  54. {typedal-3.9.1 → typedal-3.9.3}/tests/test_row.py +0 -0
  55. {typedal-3.9.1 → typedal-3.9.3}/tests/test_stats.py +0 -0
  56. {typedal-3.9.1 → typedal-3.9.3}/tests/test_table.py +0 -0
  57. {typedal-3.9.1 → typedal-3.9.3}/tests/test_web2py.py +0 -0
  58. {typedal-3.9.1 → typedal-3.9.3}/tests/test_xx_others.py +0 -0
  59. {typedal-3.9.1 → typedal-3.9.3}/tests/timings.py +0 -0
@@ -2,6 +2,18 @@
2
2
 
3
3
  <!--next-version-placeholder-->
4
4
 
5
+ ## v3.9.3 (2024-11-08)
6
+
7
+ ### Fix
8
+
9
+ * **p4w:** Actually passing the 'uri' to connect to a database in singleton mode would be pretty useful no? ([`e29a0bb`](https://github.com/trialandsuccess/TypeDAL/commit/e29a0bbb1b3f954d7f8a3c13704952f8ec42a799))
10
+
11
+ ## v3.9.2 (2024-11-08)
12
+
13
+ ### Fix
14
+
15
+ * 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))
16
+
5
17
  ## v3.9.1 (2024-10-25)
6
18
 
7
19
  ### Fix
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: TypeDAL
3
- Version: 3.9.1
3
+ Version: 3.9.3
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
@@ -8,7 +8,7 @@ dynamic = ["version"]
8
8
  description = 'Typing support for PyDAL'
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
11
- license = "MIT"
11
+ # license = "MIT"
12
12
  keywords = []
13
13
  authors = [
14
14
  { name = "Robin van der Noord", email = "contact@trialandsuccess.nl" },
@@ -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__ = "3.9.1"
8
+ __version__ = "3.9.3"
@@ -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 DAL(TypeDAL, Fixture): # pragma: no cover
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__(uri, *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):
@@ -0,0 +1,79 @@
1
+ import json
2
+ import tempfile
3
+ from contextlib import chdir
4
+
5
+ from pydal.validators import IS_EMAIL, IS_NOT_IN_DB
6
+
7
+ from src.typedal import TypedTable
8
+ from src.typedal.for_py4web import DAL, AuthUser, setup_py4web_tables
9
+ from src.typedal.serializers import as_json
10
+
11
+ db = DAL("sqlite:memory")
12
+
13
+
14
+ def test_P4W():
15
+ assert hasattr(DAL, "on_request")
16
+ assert hasattr(db, "on_request")
17
+
18
+
19
+ def test_serialize():
20
+ @db.define()
21
+ class JsonTable(TypedTable):
22
+ field: str
23
+
24
+ row = JsonTable.insert(field="Hey")
25
+
26
+ l = json.loads(as_json.encode(JsonTable))
27
+ assert l
28
+ assert isinstance(l, dict)
29
+ l = json.loads(as_json.encode(row))
30
+ assert isinstance(l, dict)
31
+ assert l
32
+
33
+ l = json.loads(as_json.encode(JsonTable.paginate(limit=1)))
34
+
35
+ assert l["pagination"]
36
+ assert l["data"]
37
+
38
+
39
+ def test_auth_user():
40
+ setup_py4web_tables(db)
41
+ requirements = AuthUser.email.requires
42
+
43
+ assert requirements
44
+ assert isinstance(requirements, tuple)
45
+ assert len(requirements) == 2
46
+
47
+ assert isinstance(requirements[0], IS_EMAIL)
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_1a._uri == db_1b._uri
64
+ assert db_1a._db_uid == db_1b._db_uid
65
+
66
+ assert db_2a is db_2b
67
+ assert db_2a._uri == db_2b._uri
68
+ assert db_2a._db_uid == db_2b._db_uid
69
+
70
+ assert db_1a is not db_2a
71
+ assert db_1a._uri != db_2a._uri
72
+ assert db_1a._db_uid != db_2a._db_uid
73
+
74
+ assert db_1b is not db_2b
75
+ assert db_1b._uri != db_2b._uri
76
+ assert db_1b._db_uid != db_2b._db_uid
77
+
78
+ # reset singletons for later use:
79
+ DAL._clear()
@@ -1,46 +0,0 @@
1
- import json
2
-
3
- from pydal.validators import IS_EMAIL, IS_NOT_IN_DB
4
-
5
- from src.typedal import TypedTable
6
- from src.typedal.for_py4web import DAL, AuthUser, setup_py4web_tables
7
- from src.typedal.serializers import as_json
8
-
9
- db = DAL("sqlite:memory")
10
-
11
-
12
- def test_P4W():
13
- assert hasattr(DAL, "on_request")
14
- assert hasattr(db, "on_request")
15
-
16
-
17
- def test_serialize():
18
- @db.define()
19
- class JsonTable(TypedTable):
20
- field: str
21
-
22
- row = JsonTable.insert(field="Hey")
23
-
24
- l = json.loads(as_json.encode(JsonTable))
25
- assert l
26
- assert isinstance(l, dict)
27
- l = json.loads(as_json.encode(row))
28
- assert isinstance(l, dict)
29
- assert l
30
-
31
- l = json.loads(as_json.encode(JsonTable.paginate(limit=1)))
32
-
33
- assert l["pagination"]
34
- assert l["data"]
35
-
36
-
37
- def test_auth_user():
38
- setup_py4web_tables(db)
39
- requirements = AuthUser.email.requires
40
-
41
- assert requirements
42
- assert isinstance(requirements, tuple)
43
- assert len(requirements) == 2
44
-
45
- assert isinstance(requirements[0], IS_EMAIL)
46
- assert isinstance(requirements[1], IS_NOT_IN_DB)
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