TypeDAL 4.9.2__tar.gz → 4.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.
Files changed (80) hide show
  1. typedal-4.9.3/.crush/.gitignore +1 -0
  2. typedal-4.9.3/.crush/crush.db-shm +0 -0
  3. typedal-4.9.3/.crush/crush.db-wal +0 -0
  4. typedal-4.9.3/.crush/logs/crush.log +37 -0
  5. {typedal-4.9.2 → typedal-4.9.3}/CHANGELOG.md +6 -0
  6. {typedal-4.9.2 → typedal-4.9.3}/PKG-INFO +1 -1
  7. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/__about__.py +1 -1
  8. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/query_builder.py +25 -4
  9. typedal-4.9.3/tests/__init__.py +0 -0
  10. {typedal-4.9.2 → typedal-4.9.3}/tests/test_relationships.py +27 -0
  11. /typedal-4.9.2/src/typedal/py.typed → /typedal-4.9.3/.crush/init +0 -0
  12. {typedal-4.9.2 → typedal-4.9.3}/.github/workflows/su6.yml +0 -0
  13. {typedal-4.9.2 → typedal-4.9.3}/.gitignore +0 -0
  14. {typedal-4.9.2 → typedal-4.9.3}/.readthedocs.yml +0 -0
  15. {typedal-4.9.2 → typedal-4.9.3}/README.md +0 -0
  16. {typedal-4.9.2 → typedal-4.9.3}/coverage.svg +0 -0
  17. {typedal-4.9.2 → typedal-4.9.3}/docs/10_advanced_apis.md +0 -0
  18. {typedal-4.9.2 → typedal-4.9.3}/docs/1_getting_started.md +0 -0
  19. {typedal-4.9.2 → typedal-4.9.3}/docs/2_defining_tables.md +0 -0
  20. {typedal-4.9.2 → typedal-4.9.3}/docs/3_building_queries.md +0 -0
  21. {typedal-4.9.2 → typedal-4.9.3}/docs/4_relationships.md +0 -0
  22. {typedal-4.9.2 → typedal-4.9.3}/docs/5_py4web.md +0 -0
  23. {typedal-4.9.2 → typedal-4.9.3}/docs/6_migrations.md +0 -0
  24. {typedal-4.9.2 → typedal-4.9.3}/docs/7_configuration.md +0 -0
  25. {typedal-4.9.2 → typedal-4.9.3}/docs/8_mixins.md +0 -0
  26. {typedal-4.9.2 → typedal-4.9.3}/docs/9_memoization.md +0 -0
  27. {typedal-4.9.2 → typedal-4.9.3}/docs/css/code_blocks.css +0 -0
  28. {typedal-4.9.2 → typedal-4.9.3}/docs/index.md +0 -0
  29. {typedal-4.9.2 → typedal-4.9.3}/docs/requirements.txt +0 -0
  30. {typedal-4.9.2 → typedal-4.9.3}/example_new.py +0 -0
  31. {typedal-4.9.2 → typedal-4.9.3}/example_old.py +0 -0
  32. {typedal-4.9.2 → typedal-4.9.3}/mkdocs.yml +0 -0
  33. {typedal-4.9.2 → typedal-4.9.3}/pyproject.toml +0 -0
  34. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/__init__.py +0 -0
  35. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/caching.py +0 -0
  36. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/cli.py +0 -0
  37. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/config.py +0 -0
  38. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/constants.py +0 -0
  39. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/core.py +0 -0
  40. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/define.py +0 -0
  41. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/enum_helpers.py +0 -0
  42. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/fields.py +0 -0
  43. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/for_py4web.py +0 -0
  44. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/for_web2py.py +0 -0
  45. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/helpers.py +0 -0
  46. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/mixins.py +0 -0
  47. /typedal-4.9.2/tests/__init__.py → /typedal-4.9.3/src/typedal/py.typed +0 -0
  48. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/relationships.py +0 -0
  49. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/rows.py +0 -0
  50. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/serializers/as_json.py +0 -0
  51. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/serializers/typescript.py +0 -0
  52. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/tables.py +0 -0
  53. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/types.py +0 -0
  54. {typedal-4.9.2 → typedal-4.9.3}/src/typedal/web2py_py4web_shared.py +0 -0
  55. {typedal-4.9.2 → typedal-4.9.3}/tasks.py +0 -0
  56. {typedal-4.9.2 → typedal-4.9.3}/tests/configs/simple.toml +0 -0
  57. {typedal-4.9.2 → typedal-4.9.3}/tests/configs/valid.env +0 -0
  58. {typedal-4.9.2 → typedal-4.9.3}/tests/configs/valid.toml +0 -0
  59. {typedal-4.9.2 → typedal-4.9.3}/tests/conftest.py +0 -0
  60. {typedal-4.9.2 → typedal-4.9.3}/tests/py314_tests.py +0 -0
  61. {typedal-4.9.2 → typedal-4.9.3}/tests/test_cli.py +0 -0
  62. {typedal-4.9.2 → typedal-4.9.3}/tests/test_config.py +0 -0
  63. {typedal-4.9.2 → typedal-4.9.3}/tests/test_docs_examples.py +0 -0
  64. {typedal-4.9.2 → typedal-4.9.3}/tests/test_helpers.py +0 -0
  65. {typedal-4.9.2 → typedal-4.9.3}/tests/test_json.py +0 -0
  66. {typedal-4.9.2 → typedal-4.9.3}/tests/test_main.py +0 -0
  67. {typedal-4.9.2 → typedal-4.9.3}/tests/test_mixins.py +0 -0
  68. {typedal-4.9.2 → typedal-4.9.3}/tests/test_mypy.py +0 -0
  69. {typedal-4.9.2 → typedal-4.9.3}/tests/test_orm.py +0 -0
  70. {typedal-4.9.2 → typedal-4.9.3}/tests/test_py4web.py +0 -0
  71. {typedal-4.9.2 → typedal-4.9.3}/tests/test_query_builder.py +0 -0
  72. {typedal-4.9.2 → typedal-4.9.3}/tests/test_row.py +0 -0
  73. {typedal-4.9.2 → typedal-4.9.3}/tests/test_stats.py +0 -0
  74. {typedal-4.9.2 → typedal-4.9.3}/tests/test_table.py +0 -0
  75. {typedal-4.9.2 → typedal-4.9.3}/tests/test_typescript.py +0 -0
  76. {typedal-4.9.2 → typedal-4.9.3}/tests/test_typing_mypy.md +0 -0
  77. {typedal-4.9.2 → typedal-4.9.3}/tests/test_typing_pyright.md +0 -0
  78. {typedal-4.9.2 → typedal-4.9.3}/tests/test_web2py.py +0 -0
  79. {typedal-4.9.2 → typedal-4.9.3}/tests/test_xx_others.py +0 -0
  80. {typedal-4.9.2 → typedal-4.9.3}/tests/timings.py +0 -0
@@ -0,0 +1 @@
1
+ *
Binary file
Binary file
@@ -0,0 +1,37 @@
1
+ {"time":"2026-01-20T14:19:21.359487106+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":55},"msg":"Fetching providers from Catwalk"}
2
+ {"time":"2026-01-20T14:19:21.518115889+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":63},"msg":"Catwalk providers not modified"}
3
+ {"time":"2026-01-20T14:19:21.52626179+01:00","level":"INFO","msg":"OK 20250424200609_initial.sql (1.52ms)"}
4
+ {"time":"2026-01-20T14:19:21.526651475+01:00","level":"INFO","msg":"OK 20250515105448_add_summary_message_id.sql (330.71µs)"}
5
+ {"time":"2026-01-20T14:19:21.526995425+01:00","level":"INFO","msg":"OK 20250624000000_add_created_at_indexes.sql (325.29µs)"}
6
+ {"time":"2026-01-20T14:19:21.527303588+01:00","level":"INFO","msg":"OK 20250627000000_add_provider_to_messages.sql (293.15µs)"}
7
+ {"time":"2026-01-20T14:19:21.52790648+01:00","level":"INFO","msg":"OK 20250810000000_add_is_summary_message.sql (495.71µs)"}
8
+ {"time":"2026-01-20T14:19:21.528316924+01:00","level":"INFO","msg":"OK 20250812000000_add_todos_to_sessions.sql (389.38µs)"}
9
+ {"time":"2026-01-20T14:19:21.528324939+01:00","level":"INFO","msg":"goose: successfully migrated database to version: 20250812000000"}
10
+ {"time":"2026-01-20T14:19:21.528356959+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).initLSPClients","file":"github.com/charmbracelet/crush/internal/app/lsp.go","line":21},"msg":"LSP clients initialization started in background"}
11
+ {"time":"2026-01-20T14:19:21.52843831+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.New.func1","file":"github.com/charmbracelet/crush/internal/app/app.go","line":102},"msg":"Initializing MCP clients"}
12
+ {"time":"2026-01-20T14:21:06.413595152+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
13
+ {"time":"2026-01-20T14:21:14.539289381+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
14
+ {"time":"2026-01-20T14:21:15.710688424+01:00","level":"WARN","source":{"function":"github.com/charmbracelet/crush/internal/agent/tools.init.func1","file":"github.com/charmbracelet/crush/internal/agent/tools/rg.go","line":18},"msg":"Ripgrep (rg) not found in $PATH. Some grep features might be limited or slower."}
15
+ {"time":"2026-01-20T14:21:17.08089755+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
16
+ {"time":"2026-01-20T14:21:17.151106375+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
17
+ {"time":"2026-01-20T14:22:05.503761296+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
18
+ {"time":"2026-01-20T14:26:05.030425805+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
19
+ {"time":"2026-01-20T14:36:26.778665189+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
20
+ {"time":"2026-01-20T14:38:51.314473736+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
21
+ {"time":"2026-01-20T15:02:22.602405814+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).Shutdown.func1","file":"github.com/charmbracelet/crush/internal/app/app.go","line":403},"msg":"Shutdown took 6.62949ms"}
22
+ {"time":"2026-01-20T15:02:23.719585648+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":55},"msg":"Fetching providers from Catwalk"}
23
+ {"time":"2026-01-20T15:02:23.881789126+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":63},"msg":"Catwalk providers not modified"}
24
+ {"time":"2026-01-20T15:02:23.884044691+01:00","level":"INFO","msg":"goose: no migrations to run. current version: 20250812000000"}
25
+ {"time":"2026-01-20T15:02:23.884082792+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).initLSPClients","file":"github.com/charmbracelet/crush/internal/app/lsp.go","line":21},"msg":"LSP clients initialization started in background"}
26
+ {"time":"2026-01-20T15:02:23.884273487+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.New.func1","file":"github.com/charmbracelet/crush/internal/app/app.go","line":102},"msg":"Initializing MCP clients"}
27
+ {"time":"2026-01-20T15:04:13.024457515+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
28
+ {"time":"2026-01-20T15:04:14.232072885+01:00","level":"WARN","source":{"function":"github.com/charmbracelet/crush/internal/agent/tools.init.func1","file":"github.com/charmbracelet/crush/internal/agent/tools/rg.go","line":18},"msg":"Ripgrep (rg) not found in $PATH. Some grep features might be limited or slower."}
29
+ {"time":"2026-01-20T15:11:24.612161916+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).Shutdown.func1","file":"github.com/charmbracelet/crush/internal/app/app.go","line":403},"msg":"Shutdown took 9.537141ms"}
30
+ {"time":"2026-01-20T15:11:25.263960575+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":55},"msg":"Fetching providers from Catwalk"}
31
+ {"time":"2026-01-20T15:11:25.431990051+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/config.(*catwalkSync).Get.func1","file":"github.com/charmbracelet/crush/internal/config/catwalk.go","line":63},"msg":"Catwalk providers not modified"}
32
+ {"time":"2026-01-20T15:11:25.434282035+01:00","level":"INFO","msg":"goose: no migrations to run. current version: 20250812000000"}
33
+ {"time":"2026-01-20T15:11:25.434366662+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.(*App).initLSPClients","file":"github.com/charmbracelet/crush/internal/app/lsp.go","line":21},"msg":"LSP clients initialization started in background"}
34
+ {"time":"2026-01-20T15:11:25.434579879+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/app.New.func1","file":"github.com/charmbracelet/crush/internal/app/app.go","line":102},"msg":"Initializing MCP clients"}
35
+ {"time":"2026-01-20T15:24:40.456010578+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).generateTitle","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":788},"msg":"generated title with small model"}
36
+ {"time":"2026-01-20T15:24:51.673808433+01:00","level":"WARN","source":{"function":"github.com/charmbracelet/crush/internal/agent/tools.init.func1","file":"github.com/charmbracelet/crush/internal/agent/tools/rg.go","line":18},"msg":"Ripgrep (rg) not found in $PATH. Some grep features might be limited or slower."}
37
+ {"time":"2026-01-20T15:26:03.868420566+01:00","level":"INFO","source":{"function":"github.com/charmbracelet/crush/internal/agent.(*sessionAgent).Cancel","file":"github.com/charmbracelet/crush/internal/agent/agent.go","line":907},"msg":"Request cancellation initiated","session_id":"4c2d1684-8db2-4ffd-83bb-9c08fe850f29"}
@@ -2,6 +2,12 @@
2
2
 
3
3
  <!--next-version-placeholder-->
4
4
 
5
+ ## v4.9.3 (2026-07-03)
6
+
7
+ ### Fix
8
+
9
+ * Pagination count with joined relationships ([`2eaefc0`](https://github.com/trialandsuccess/TypeDAL/commit/2eaefc051a94d4a4204164e0773a8d7691aae63e))
10
+
5
11
  ## v4.9.2 (2026-07-02)
6
12
 
7
13
  ### Fix
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TypeDAL
3
- Version: 4.9.2
3
+ Version: 4.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
@@ -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__ = "4.9.2"
8
+ __version__ = "4.9.3"
@@ -837,6 +837,7 @@ class QueryBuilder[T_MetaInstance: _TypedTable]:
837
837
 
838
838
  if joins:
839
839
  kwargs["join"] = joins
840
+ kwargs["distinct"] = True
840
841
 
841
842
  ids = db(query)._select(model.id, **kwargs)
842
843
  query = model.id.belongs(ids)
@@ -1128,19 +1129,31 @@ class QueryBuilder[T_MetaInstance: _TypedTable]:
1128
1129
  """
1129
1130
  yield from self.collect()
1130
1131
 
1131
- def __count(self, db: TypeDAL, distinct: t.Optional[bool] = None) -> Query:
1132
+ def __count(
1133
+ self,
1134
+ db: TypeDAL,
1135
+ distinct: t.Optional[bool] = None,
1136
+ *,
1137
+ include_left_for_distinct: bool = True,
1138
+ ) -> Query:
1132
1139
  # internal, shared logic between .count and ._count
1133
1140
  model = self.model
1134
1141
  query = self.query
1135
1142
  for key, relation in self.relationships.items():
1136
- if (not relation.condition or relation.join != "inner") and not distinct:
1143
+ if not relation.condition:
1144
+ continue
1145
+
1146
+ include_left_join = distinct and include_left_for_distinct
1147
+ if relation.join != "inner" and not include_left_join:
1137
1148
  continue
1138
1149
 
1139
1150
  other = relation.get_table(db)
1140
1151
  if not distinct:
1141
1152
  # todo: can this lead to other issues?
1142
1153
  other = other.with_alias(f"{key}_{hash(relation)}")
1143
- query &= relation.condition(model, other)
1154
+
1155
+ if relation.condition is not None:
1156
+ query &= relation.condition(model, other)
1144
1157
 
1145
1158
  return query
1146
1159
 
@@ -1175,12 +1188,20 @@ class QueryBuilder[T_MetaInstance: _TypedTable]:
1175
1188
  require_permission(self._permissions, "read")
1176
1189
  return bool(self.count())
1177
1190
 
1191
+ def __pagination_count(self) -> int:
1192
+ if not self.relationships:
1193
+ return self.count()
1194
+
1195
+ db = self._get_db()
1196
+ query = self.__count(db, distinct=self.model.id, include_left_for_distinct=False)
1197
+ return db(query).count(self.model.id)
1198
+
1178
1199
  def __paginate(
1179
1200
  self,
1180
1201
  limit: int,
1181
1202
  page: int = 1,
1182
1203
  ) -> "QueryBuilder[T_MetaInstance]":
1183
- available = self.count()
1204
+ available = self.__pagination_count()
1184
1205
 
1185
1206
  _from = limit * (page - 1)
1186
1207
  _to = (limit * page) if limit else available
File without changes
@@ -888,6 +888,33 @@ def test_join_with_select():
888
888
  assert not hasattr(user.articles[0], "title")
889
889
 
890
890
 
891
+ def test_paginate_with_inner_join_uses_root_entities():
892
+ _setup_data()
893
+
894
+ page1 = User.join("articles", method="inner").orderby(~User.id).paginate(limit=2, page=1)
895
+ page2 = page1.next()
896
+ page1_again = page2.previous()
897
+
898
+ assert [user.id for user in page1] == [4, 3]
899
+ assert [user.id for user in page2] == [2]
900
+ assert [user.id for user in page1_again] == [4, 3]
901
+
902
+ assert sorted(article.title for article in page1.first().articles) == [
903
+ "Untagged Article 1",
904
+ "Untagged Article 2",
905
+ ]
906
+ assert [article.title for article in page2.first().articles] == ["Article 1"]
907
+
908
+ assert page1.pagination["total_items"] == 3
909
+ assert page1.pagination["total_pages"] == 2
910
+ assert page1.pagination["has_next_page"] is True
911
+ assert page2.pagination["has_next_page"] is False
912
+ assert page2.pagination["has_prev_page"] is True
913
+
914
+ with pytest.raises(StopIteration):
915
+ page2.next()
916
+
917
+
891
918
  def test_count_with_join():
892
919
  _setup_data()
893
920
 
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