sqlakit 0.15.0__tar.gz → 0.16.0__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 (30) hide show
  1. {sqlakit-0.15.0 → sqlakit-0.16.0}/PKG-INFO +1 -1
  2. {sqlakit-0.15.0 → sqlakit-0.16.0}/pyproject.toml +1 -1
  3. {sqlakit-0.15.0 → sqlakit-0.16.0}/pyproject.toml.orig +1 -1
  4. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_query.py +82 -3
  5. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/orm.py +4 -0
  6. {sqlakit-0.15.0 → sqlakit-0.16.0}/LICENSE +0 -0
  7. {sqlakit-0.15.0 → sqlakit-0.16.0}/README.md +0 -0
  8. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/__init__.py +0 -0
  9. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_base.py +0 -0
  10. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_cli.py +0 -0
  11. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_db.py +0 -0
  12. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_debugserver.py +0 -0
  13. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_discovery.py +0 -0
  14. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_model.py +0 -0
  15. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_recording.py +0 -0
  16. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_registry.py +0 -0
  17. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_routing.py +0 -0
  18. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/_sql.py +0 -0
  19. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/__init__.py +0 -0
  20. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/_db.py +0 -0
  21. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/_registry.py +0 -0
  22. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/orm.py +0 -0
  23. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/asyncio/sql.py +0 -0
  24. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/debugserver.html +0 -0
  25. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/exceptions.py +0 -0
  26. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/py.typed +0 -0
  27. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/pytest_plugin.py +0 -0
  28. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/sql.py +0 -0
  29. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/testing.py +0 -0
  30. {sqlakit-0.15.0 → sqlakit-0.16.0}/sqlakit/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: sqlakit
3
- Version: 0.15.0
3
+ Version: 0.16.0
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.15.0"
3
+ version = "0.16.0"
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.15.0"
3
+ version = "0.16.0"
4
4
  description = "A toolkit for SQLAlchemy applications."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -24,9 +24,14 @@ from sqlalchemy.ext.compiler import compiles
24
24
  from sqlalchemy.orm import (
25
25
  InstrumentedAttribute,
26
26
  contains_eager,
27
+ defer,
27
28
  joinedload,
29
+ load_only,
28
30
  selectinload,
29
31
  subqueryload,
32
+ undefer,
33
+ undefer_group,
34
+ with_expression,
30
35
  )
31
36
  from sqlalchemy.orm.exc import MultipleResultsFound, NoResultFound
32
37
  from sqlalchemy.sql import operators
@@ -507,10 +512,23 @@ class BaseQuery(Generic[ModelT]):
507
512
  self._reject_statement("where")
508
513
  return self.with_select(self._select.where(*criteria))
509
514
 
510
- def filter_by(self, **values: Any) -> Self: # noqa: ANN401
511
- """Narrow the rows by equality, as `Select.filter_by` does."""
515
+ def filter_by(
516
+ self,
517
+ values: Mapping[str, Any] | None = None,
518
+ /,
519
+ **fields: Any, # noqa: ANN401
520
+ ) -> Self:
521
+ """Narrow the rows by equality, as `Select.filter_by` does.
522
+
523
+ ```python
524
+ db.query(User).filter_by(team="red")
525
+ db.query(User).filter_by(request.query_params)
526
+ ```
527
+
528
+ The fields are keywords, a mapping, or both, as `create()` takes them.
529
+ """
512
530
  self._reject_statement("filter_by")
513
- return self.with_select(self._select.filter_by(**values))
531
+ return self.with_select(self._select.filter_by(**merged(values, fields)))
514
532
 
515
533
  def join(
516
534
  self,
@@ -659,6 +677,67 @@ class BaseQuery(Generic[ModelT]):
659
677
  """Read a relationship from a join this query already makes."""
660
678
  return self.options(_chain(contains_eager, keys))
661
679
 
680
+ def load_only(self, *columns: Any) -> Self: # noqa: ANN401
681
+ """Load these columns of the row, and defer the rest.
682
+
683
+ ```python
684
+ db.query(User).load_only(User.id, User.name).all()
685
+ ```
686
+
687
+ The rows are still instances: a column left out is read from the
688
+ database when something touches it, one statement per instance, which
689
+ is the cost this trades the narrower row for. `only_columns` is the
690
+ other one: it gives the instances up and reads values.
691
+ """
692
+ return self.options(load_only(*columns))
693
+
694
+ def defer(self, *columns: Any) -> Self: # noqa: ANN401
695
+ """Leave these columns out of the row until something reads them.
696
+
697
+ ```python
698
+ db.query(Post).defer(Post.body).all()
699
+ ```
700
+
701
+ For the wide column of a table read for everything else.
702
+ """
703
+ return self.options(*(defer(column) for column in columns))
704
+
705
+ def undefer(self, *columns: Any) -> Self: # noqa: ANN401
706
+ """Load these columns with the row, though the model defers them.
707
+
708
+ ```python
709
+ db.query(Post).undefer(Post.body).all()
710
+ ```
711
+
712
+ The other side of `mapped_column(deferred=True)`, for the read that
713
+ wants the column after all.
714
+ """
715
+ return self.options(*(undefer(column) for column in columns))
716
+
717
+ def undefer_group(self, name: str) -> Self:
718
+ """Load the columns a model defers under this group name.
719
+
720
+ ```python
721
+ db.query(Post).undefer_group("body").all()
722
+ ```
723
+
724
+ The group is the one `mapped_column(deferred_group="body")` names, for
725
+ the columns a read wants together or not at all.
726
+ """
727
+ return self.options(undefer_group(name))
728
+
729
+ def with_expression(self, key: Any, expression: Any) -> Self: # noqa: ANN401
730
+ """Give a `query_expression()` attribute its value for this read.
731
+
732
+ ```python
733
+ db.query(Post).with_expression(Post.comments, _comment_count()).all()
734
+ ```
735
+
736
+ The attribute holds what this statement selects into it, so a count or
737
+ a window function arrives on the instance rather than beside it.
738
+ """
739
+ return self.options(with_expression(key, expression))
740
+
662
741
  def with_for_update(
663
742
  self,
664
743
  *,
@@ -327,6 +327,10 @@ class Query(BaseQuery[ModelT]):
327
327
  ```python
328
328
  names = User.query.where(User.is_active).only_columns(User.name).all()
329
329
  ```
330
+
331
+ One column arrives as values and several as tuples, and neither is an
332
+ instance. `load_only` is the other one: the rows stay instances, and
333
+ the columns it leaves out are read when something touches them.
330
334
  """
331
335
  return ColumnQuery(
332
336
  self.model,
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