Skip to content

Commit f84ec5e

Browse files
Abel Milashclaude
andcommitted
Replace _QB TypeVar with Self in _QueryBuilderBase fluent methods
Self (from typing, under TYPE_CHECKING) is the idiomatic replacement for the self-referential TypeVar pattern. With `from __future__ import annotations` already in place, Self is never evaluated at runtime — only used by type checkers. Method signatures in docs now show `Self` instead of the private `_QB` TypeVar. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d43fa58 commit f84ec5e

1 file changed

Lines changed: 18 additions & 12 deletions

File tree

src/PowerPlatform/Dataverse/models/query_builder.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,16 @@
4949

5050
from __future__ import annotations
5151

52+
import sys
5253
import warnings
53-
from typing import Any, Iterator, List, Optional, TypeVar, TypedDict, Union
54+
from typing import Any, Iterator, List, Optional, TypedDict, Union
55+
56+
if sys.version_info >= (3, 11):
57+
from typing import Self
58+
else:
59+
from typing import TypeVar
60+
61+
Self = TypeVar("Self", bound="_QueryBuilderBase") # type: ignore[assignment]
5462

5563
import pandas as pd
5664

@@ -62,8 +70,6 @@
6270
# Sentinel for detecting when by_page is explicitly passed to execute()
6371
_BY_PAGE_UNSET = object()
6472

65-
_QB = TypeVar("_QB", bound="_QueryBuilderBase")
66-
6773

6874
class QueryParams(TypedDict, total=False):
6975
"""Typed dictionary returned by :meth:`QueryBuilder.build`.
@@ -203,7 +209,7 @@ def __init__(self, table: str) -> None:
203209

204210
# ----------------------------------------------------------------- select
205211

206-
def select(self: _QB, *columns: str) -> _QB:
212+
def select(self, *columns: str) -> Self:
207213
"""Select specific columns to retrieve.
208214
209215
Column names are passed as-is; the OData layer lowercases them
@@ -221,7 +227,7 @@ def select(self: _QB, *columns: str) -> _QB:
221227

222228
# ------------------------------------------------------ filter: expression tree
223229

224-
def where(self: _QB, expression: filters.FilterExpression) -> _QB:
230+
def where(self, expression: filters.FilterExpression) -> Self:
225231
"""Add a composable filter expression.
226232
227233
Accepts a :class:`~PowerPlatform.Dataverse.models.filters.FilterExpression`
@@ -250,7 +256,7 @@ def where(self: _QB, expression: filters.FilterExpression) -> _QB:
250256

251257
# --------------------------------------------------------------- ordering
252258

253-
def order_by(self: _QB, column: str, descending: bool = False) -> _QB:
259+
def order_by(self, column: str, descending: bool = False) -> Self:
254260
"""Add sorting order.
255261
256262
Can be called multiple times for multi-column sorting.
@@ -265,7 +271,7 @@ def order_by(self: _QB, column: str, descending: bool = False) -> _QB:
265271

266272
# --------------------------------------------------------------- pagination
267273

268-
def top(self: _QB, count: int) -> _QB:
274+
def top(self, count: int) -> Self:
269275
"""Limit the total number of results.
270276
271277
:param count: Maximum number of records to return (must be >= 1).
@@ -277,7 +283,7 @@ def top(self: _QB, count: int) -> _QB:
277283
self._top = count
278284
return self
279285

280-
def page_size(self: _QB, size: int) -> _QB:
286+
def page_size(self, size: int) -> Self:
281287
"""Set the number of records per page.
282288
283289
Controls how many records are returned in each page/batch
@@ -292,7 +298,7 @@ def page_size(self: _QB, size: int) -> _QB:
292298
self._page_size = size
293299
return self
294300

295-
def count(self: _QB) -> _QB:
301+
def count(self) -> Self:
296302
"""Request a count of matching records in the response.
297303
298304
Adds ``$count=true`` to the query, causing the server to include
@@ -311,7 +317,7 @@ def count(self: _QB) -> _QB:
311317
self._count = True
312318
return self
313319

314-
def include_formatted_values(self: _QB) -> _QB:
320+
def include_formatted_values(self) -> Self:
315321
"""Request formatted values in the response.
316322
317323
Adds ``Prefer: odata.include-annotations="OData.Community.Display.V1.FormattedValue"``
@@ -341,7 +347,7 @@ def include_formatted_values(self: _QB) -> _QB:
341347
self._include_annotations = "OData.Community.Display.V1.FormattedValue"
342348
return self
343349

344-
def include_annotations(self: _QB, annotation: str = "*") -> _QB:
350+
def include_annotations(self, annotation: str = "*") -> Self:
345351
"""Request specific OData annotations in the response.
346352
347353
Sets the ``Prefer: odata.include-annotations`` header. Use ``"*"``
@@ -369,7 +375,7 @@ def include_annotations(self: _QB, annotation: str = "*") -> _QB:
369375

370376
# --------------------------------------------------------------- expand
371377

372-
def expand(self: _QB, *relations: Union[str, ExpandOption]) -> _QB:
378+
def expand(self, *relations: Union[str, ExpandOption]) -> Self:
373379
"""Expand navigation properties.
374380
375381
Accepts plain navigation property names (case-sensitive, passed

0 commit comments

Comments
 (0)