Skip to content

Commit deeab9e

Browse files
authored
fix(docs): adjust title formatting for smaller screens (#328)
* fix: formatting for smaller screens * fix: linting
1 parent 53d32c1 commit deeab9e

File tree

2 files changed

+89
-165
lines changed

2 files changed

+89
-165
lines changed

advanced_alchemy/filters.py

Lines changed: 30 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@
44
enhance SQLAlchemy query construction. It implements type-safe, reusable filter patterns
55
for common database query operations.
66
7-
Args:
8-
None
9-
10-
Returns:
11-
None
12-
137
Features:
148
Type-safe filter construction, datetime range filtering, collection-based filtering,
159
pagination support, search operations, and customizable ordering.
@@ -35,6 +29,7 @@
3529
- :class:`sqlalchemy.sql.expression.Select`: Core SQLAlchemy select expression
3630
- :class:`sqlalchemy.orm.Query`: SQLAlchemy ORM query interface
3731
- :mod:`advanced_alchemy.base`: Base model definitions
32+
3833
"""
3934

4035
from __future__ import annotations
@@ -94,24 +89,6 @@ class StatementFilter(ABC):
9489
This class defines the interface for all filter types in the system. Each filter
9590
implementation must provide a method to append its filtering logic to an existing
9691
SQLAlchemy statement.
97-
98-
Args:
99-
None
100-
101-
Attributes:
102-
None
103-
104-
Example:
105-
Implementing a custom filter::
106-
107-
class CustomFilter(StatementFilter):
108-
def append_to_statement(self, statement, model):
109-
return statement.where(model.column == "value")
110-
111-
See Also:
112-
- :class:`.BeforeAfter`: DateTime range filtering implementation
113-
- :class:`.CollectionFilter`: Collection-based filtering implementation
114-
- :class:`sqlalchemy.sql.expression.Select`: SQLAlchemy select expression
11592
"""
11693

11794
@abstractmethod
@@ -175,22 +152,13 @@ class BeforeAfter(StatementFilter):
175152
after : datetime | None
176153
Filter results where field is later than this value
177154
178-
Example:
179-
--------
180-
>>> filter = BeforeAfter(
181-
... field_name="created_at",
182-
... before=datetime(2024, 1, 1),
183-
... after=datetime(2023, 1, 1),
184-
... )
185-
>>> statement = filter.append_to_statement(select(Model), Model)
186-
187155
Note:
188156
-----
189-
If either `before` or `after` is None, that boundary condition is not applied.
157+
If either `before` or `after` is None, that boundary condition is not applied.
190158
191159
See Also:
192-
--------
193-
:class:`OnBeforeAfter` : Inclusive datetime range filtering
160+
---------
161+
:class:`OnBeforeAfter` : Inclusive datetime range filtering
194162
"""
195163

196164
field_name: str
@@ -237,7 +205,7 @@ class OnBeforeAfter(StatementFilter):
237205
Filter results where field is on or later than this value
238206
239207
Example:
240-
--------
208+
-------
241209
>>> filter = OnBeforeAfter(
242210
... field_name="updated_at",
243211
... on_or_before=datetime(2024, 1, 1),
@@ -246,7 +214,7 @@ class OnBeforeAfter(StatementFilter):
246214
>>> statement = filter.append_to_statement(select(Model), Model)
247215
248216
Note:
249-
-----
217+
----
250218
If either `on_or_before` or `on_or_after` is None, that boundary condition
251219
is not applied.
252220
@@ -286,11 +254,10 @@ def append_to_statement(self, statement: StatementTypeT, model: type[ModelT]) ->
286254

287255

288256
class InAnyFilter(StatementFilter, ABC):
289-
"""Abstract base class for statement filters that support the `prefer_any` flag.
257+
"""Base class for filters using IN or ANY operators.
290258
291-
This class serves as a foundation for filters utilizing the ``prefer_any``
292-
parameter to select between different comparisons (e.g., using SQLAlchemy's
293-
any_ operator vs. in_ operator).
259+
This abstract class provides common functionality for filters that check
260+
membership in a collection using either the SQL IN operator or the ANY operator.
294261
"""
295262

296263

@@ -300,28 +267,23 @@ class CollectionFilter(InAnyFilter, Generic[T]):
300267
301268
This filter restricts records based on a field's presence in a collection of values.
302269
303-
Parameters
304-
----------
305-
field_name : str
306-
Name of the model attribute to filter on
307-
values : abc.Collection[T] | None
308-
Values for the ``IN`` clause. If this is None, no filter is applied.
309-
An empty list will force an empty result set (WHERE 1=-1).
270+
The filter supports both ``IN`` and ``ANY`` operators for collection membership testing.
271+
Use ``prefer_any=True`` in ``append_to_statement`` to use the ``ANY`` operator.
310272
"""
311273

312274
field_name: str
313275
"""Name of the model attribute to filter on."""
314276
values: abc.Collection[T] | None
315-
"""Values for the IN clause. If None, this filter is not applied.
316-
If an empty list, an empty result set is returned."""
277+
"""Values for the ``IN`` clause. If this is None, no filter is applied.
278+
An empty list will force an empty result set (WHERE 1=-1)"""
317279

318280
def append_to_statement(
319281
self,
320282
statement: StatementTypeT,
321283
model: type[ModelT],
322284
prefer_any: bool = False,
323285
) -> StatementTypeT:
324-
"""Apply a WHERE ... IN or WHERE ... ANY(...) clause to the statement.
286+
"""Apply a WHERE ... IN or WHERE ... ANY (...) clause to the statement.
325287
326288
Parameters
327289
----------
@@ -330,8 +292,8 @@ def append_to_statement(
330292
model : type[ModelT]
331293
The SQLAlchemy model class
332294
prefer_any : bool, optional
333-
If True, uses the SQLAlchemy any_ operator instead of in_
334-
for the filter condition
295+
If True, uses the SQLAlchemy :func:`any_` operator instead of
296+
:func:`in_` for the filter condition
335297
336298
Returns:
337299
--------
@@ -355,19 +317,23 @@ class NotInCollectionFilter(InAnyFilter, Generic[T]):
355317
356318
This filter restricts records based on a field's absence in a collection of values.
357319
320+
The filter supports both ``NOT IN`` and ``!= ANY`` operators for collection exclusion.
321+
Use ``prefer_any=True`` in ``append_to_statement`` to use the ``ANY`` operator.
322+
358323
Parameters
359324
----------
360325
field_name : str
361326
Name of the model attribute to filter on
362327
values : abc.Collection[T] | None
363328
Values for the ``NOT IN`` clause. If this is None or empty,
364329
the filter is not applied.
330+
365331
"""
366332

367333
field_name: str
368334
"""Name of the model attribute to filter on."""
369335
values: abc.Collection[T] | None
370-
"""Values for the NOT IN clause. If None or empty, no filter is applied."""
336+
"""Values for the ``NOT IN`` clause. If None or empty, no filter is applied."""
371337

372338
def append_to_statement(
373339
self,
@@ -384,8 +350,8 @@ def append_to_statement(
384350
model : type[ModelT]
385351
The SQLAlchemy model class
386352
prefer_any : bool, optional
387-
If True, uses the SQLAlchemy any_ operator instead of notin_
388-
for the filter condition
353+
If True, uses the SQLAlchemy :func:`any_` operator instead of
354+
:func:`notin_` for the filter condition
389355
390356
Returns:
391357
--------
@@ -416,20 +382,6 @@ class LimitOffset(PaginationFilter):
416382
Implements traditional pagination using SQL LIMIT and OFFSET clauses.
417383
Only applies to SELECT statements; other statement types are returned unmodified.
418384
419-
Args:
420-
limit: Maximum number of rows to return
421-
offset: Number of rows to skip before returning results
422-
423-
Attributes:
424-
limit: Maximum number of rows to return
425-
offset: Number of rows to skip before returning results
426-
427-
Example:
428-
Basic pagination usage::
429-
430-
filter = LimitOffset(limit=10, offset=20)
431-
statement = filter.append_to_statement(select(Model), Model)
432-
433385
Note:
434386
This filter only modifies SELECT statements. For other statement types
435387
(UPDATE, DELETE), the statement is returned unchanged.
@@ -440,7 +392,9 @@ class LimitOffset(PaginationFilter):
440392
"""
441393

442394
limit: int
395+
"""Maximum number of rows to return."""
443396
offset: int
397+
"""Number of rows to skip before returning results."""
444398

445399
def append_to_statement(self, statement: StatementTypeT, model: type[ModelT]) -> StatementTypeT:
446400
"""Apply LIMIT/OFFSET pagination to the statement.
@@ -470,25 +424,6 @@ class OrderBy(StatementFilter):
470424
Appends an ORDER BY clause to SELECT statements, sorting records by the
471425
specified field in ascending or descending order.
472426
473-
Args:
474-
field_name: Name of the model attribute to sort on
475-
sort_order: Sort direction ("asc" or "desc"), defaults to "asc"
476-
477-
Attributes:
478-
field_name: Name of the model attribute to sort on
479-
sort_order: Sort direction ("asc" or "desc")
480-
481-
Example:
482-
Basic sorting usage::
483-
484-
# Ascending order (default)
485-
filter = OrderBy(field_name="created_at")
486-
statement = filter.append_to_statement(select(Model), Model)
487-
488-
# Descending order
489-
filter = OrderBy(field_name="priority", sort_order="desc")
490-
statement = filter.append_to_statement(select(Model), Model)
491-
492427
Note:
493428
This filter only modifies SELECT statements. For other statement types,
494429
the statement is returned unchanged.
@@ -500,7 +435,9 @@ class OrderBy(StatementFilter):
500435
"""
501436

502437
field_name: str
438+
"""Name of the model attribute to sort on."""
503439
sort_order: Literal["asc", "desc"] = "asc"
440+
"""Sort direction ("asc" or "desc")."""
504441

505442
def append_to_statement(self, statement: StatementTypeT, model: type[ModelT]) -> StatementTypeT:
506443
"""Append an ORDER BY clause to the statement.
@@ -533,33 +470,6 @@ class SearchFilter(StatementFilter):
533470
Implements text search using SQL LIKE or ILIKE operators. Can search across
534471
multiple fields using OR conditions.
535472
536-
Args:
537-
field_name: Name or set of names of model attributes to search on
538-
value: Text to match within the field(s)
539-
ignore_case: If True, uses ILIKE for case-insensitive matching
540-
541-
Attributes:
542-
field_name: Name or set of names of model attributes to search on
543-
value: Text to match within the field(s)
544-
ignore_case: Whether to use case-insensitive matching
545-
546-
Example:
547-
Single field search::
548-
549-
filter = SearchFilter(
550-
field_name="name", value="john", ignore_case=True
551-
)
552-
statement = filter.append_to_statement(select(Model), Model)
553-
554-
Multi-field search::
555-
556-
filter = SearchFilter(
557-
field_name={"name", "email"},
558-
value="example",
559-
ignore_case=True,
560-
)
561-
statement = filter.append_to_statement(select(Model), Model)
562-
563473
Note:
564474
The search pattern automatically adds wildcards before and after the search
565475
value, equivalent to SQL pattern '%value%'.
@@ -571,8 +481,11 @@ class SearchFilter(StatementFilter):
571481
"""
572482

573483
field_name: str | set[str]
484+
"""Name or set of names of model attributes to search on."""
574485
value: str
486+
"""Text to match within the field(s)."""
575487
ignore_case: bool | None = False
488+
"""Whether to use case-insensitive matching."""
576489

577490
@property
578491
def _operator(self) -> Callable[..., ColumnElement[bool]]:
@@ -656,23 +569,6 @@ class NotInSearchFilter(SearchFilter):
656569
value: Text to exclude from the field(s)
657570
ignore_case: If True, uses NOT ILIKE for case-insensitive matching
658571
659-
Example:
660-
Single field exclusion::
661-
662-
filter = NotInSearchFilter(
663-
field_name="name", value="test", ignore_case=True
664-
)
665-
statement = filter.append_to_statement(select(Model), Model)
666-
667-
Multi-field exclusion::
668-
669-
filter = NotInSearchFilter(
670-
field_name={"name", "description"},
671-
value="temp",
672-
ignore_case=True,
673-
)
674-
statement = filter.append_to_statement(select(Model), Model)
675-
676572
Note:
677573
Uses AND for multiple fields, meaning records matching any field will be excluded.
678574

0 commit comments

Comments
 (0)