sqlakit 0.7.0__tar.gz → 0.7.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.
Files changed (26) hide show
  1. {sqlakit-0.7.0 → sqlakit-0.7.1}/PKG-INFO +1 -1
  2. {sqlakit-0.7.0 → sqlakit-0.7.1}/pyproject.toml +1 -1
  3. {sqlakit-0.7.0 → sqlakit-0.7.1}/pyproject.toml.orig +1 -1
  4. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/__init__.py +2 -0
  5. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_query.py +30 -0
  6. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/exceptions.py +13 -0
  7. {sqlakit-0.7.0 → sqlakit-0.7.1}/LICENSE +0 -0
  8. {sqlakit-0.7.0 → sqlakit-0.7.1}/README.md +0 -0
  9. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_base.py +0 -0
  10. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_db.py +0 -0
  11. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_discovery.py +0 -0
  12. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_model.py +0 -0
  13. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_recording.py +0 -0
  14. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_registry.py +0 -0
  15. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_routing.py +0 -0
  16. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/_sql.py +0 -0
  17. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/asyncio/__init__.py +0 -0
  18. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/asyncio/_db.py +0 -0
  19. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/asyncio/_registry.py +0 -0
  20. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/asyncio/orm.py +0 -0
  21. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/asyncio/sql.py +0 -0
  22. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/orm.py +0 -0
  23. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/py.typed +0 -0
  24. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/sql.py +0 -0
  25. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/testing.py +0 -0
  26. {sqlakit-0.7.0 → sqlakit-0.7.1}/sqlakit/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlakit
3
- Version: 0.7.0
3
+ Version: 0.7.1
4
4
  Summary: A toolkit for SQLAlchemy applications.
5
5
  Keywords: sqlalchemy,database,orm,sql,asyncio
6
6
  Author: Anton Ruhlov
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sqlakit"
3
- version = "0.7.0"
3
+ version = "0.7.1"
4
4
  description = "A toolkit for SQLAlchemy applications."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sqlakit"
3
- version = "0.7.0"
3
+ version = "0.7.1"
4
4
  description = "A toolkit for SQLAlchemy applications."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -18,6 +18,7 @@ from .exceptions import (
18
18
  AsyncFilterError,
19
19
  BulkQueryError,
20
20
  ConflictingDatabaseUrlError,
21
+ ConflictingJoinError,
21
22
  DatabaseAlreadyConfiguredError,
22
23
  DatabaseNotConfiguredError,
23
24
  DefaultAliasError,
@@ -69,6 +70,7 @@ __all__ = [
69
70
  "AsyncFilterError",
70
71
  "BulkQueryError",
71
72
  "ConflictingDatabaseUrlError",
73
+ "ConflictingJoinError",
72
74
  "CursorPage",
73
75
  "Database",
74
76
  "DatabaseAlreadyConfiguredError",
@@ -37,6 +37,7 @@ from typing_extensions import TypeVar
37
37
  from ._model import resolve_alias, soft_delete_column
38
38
  from .exceptions import (
39
39
  BulkQueryError,
40
+ ConflictingJoinError,
40
41
  InstanceNotFoundError,
41
42
  InvalidCursorError,
42
43
  InvalidNullsError,
@@ -1015,11 +1016,13 @@ def ordered(
1015
1016
  else {_field_named(one, fields) for one in ignore_case}
1016
1017
  )
1017
1018
  clauses = []
1019
+ joined: dict[str, Any] = {}
1018
1020
  for criterion in named:
1019
1021
  clause, join = _ordering_for(criterion, fields, ignore_case=folded)
1020
1022
  clauses.append(_with_nulls(clause, nulls))
1021
1023
  if join is not None:
1022
1024
  target, onclause, outer = join
1025
+ _reject_conflicting_join(joined, target, onclause)
1023
1026
  if not _is_joined(select, target):
1024
1027
  select = select.join(target, onclause, isouter=outer)
1025
1028
  return select.order_by(*clauses)
@@ -1176,6 +1179,33 @@ def _join_for(field: Any) -> tuple[Any, None, bool] | None: # noqa: ANN401
1176
1179
  return None if table is None else (table, None, True)
1177
1180
 
1178
1181
 
1182
+ def _reject_conflicting_join(
1183
+ joined: dict[str, Any],
1184
+ target: Any, # noqa: ANN401
1185
+ onclause: Any, # noqa: ANN401
1186
+ ) -> None:
1187
+ """Refuse a second join of one table on another condition.
1188
+
1189
+ A statement joins a table once, so the second condition would be dropped
1190
+ and the field would order by the first one's rows.
1191
+
1192
+ Raises:
1193
+ ConflictingJoinError: if the table is already joined on something else.
1194
+
1195
+ """
1196
+ identity = _join_identity(target)
1197
+ if identity is None:
1198
+ return
1199
+ if identity not in joined:
1200
+ joined[identity] = onclause
1201
+ return
1202
+ first = joined[identity]
1203
+ if first is None or onclause is None:
1204
+ return
1205
+ if not first.compare(onclause):
1206
+ raise ConflictingJoinError(identity)
1207
+
1208
+
1179
1209
  def _is_joined(select: sa.Select[Any], target: Any) -> bool: # noqa: ANN401
1180
1210
  """Whether this statement already reaches what a field needs."""
1181
1211
  wanted = _join_identity(target)
@@ -9,6 +9,7 @@ __all__ = [
9
9
  "AsyncFilterError",
10
10
  "BulkQueryError",
11
11
  "ConflictingDatabaseUrlError",
12
+ "ConflictingJoinError",
12
13
  "DatabaseAlreadyConfiguredError",
13
14
  "DatabaseNotConfiguredError",
14
15
  "DefaultAliasError",
@@ -426,6 +427,18 @@ class InvalidOrderFieldError(SQLAKitError, TypeError):
426
427
  )
427
428
 
428
429
 
430
+ class ConflictingJoinError(SQLAKitError, TypeError):
431
+ """Raised when two ordering fields join one table on different conditions."""
432
+
433
+ def __init__(self, table: str) -> None:
434
+ self.table = table
435
+ super().__init__(
436
+ f"Two ordering fields join `{table}` on different conditions, and a "
437
+ f"statement joins it once. Alias it with `sqlalchemy.orm.aliased` so "
438
+ f"that each field joins an alias of its own."
439
+ )
440
+
441
+
429
442
  class InvalidNullsError(SQLAKitError, ValueError):
430
443
  """Raised when ``order_by`` is told to put the nulls somewhere else.
431
444
 
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