-
Notifications
You must be signed in to change notification settings - Fork 136
chore: @requires
for backend method constraints
#2371
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Just aiming for signature preservation *first*
- Was able to remove it prior to #2374 - Now has **52 statements** https://results.pre-commit.ci/run/github/760058710/1744454838.3JiSpZ7eSm2coYbvwwDupA
Been think about an alternative spelling which could be more easily adapted for other requirements. Imports
from __future__ import annotations
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from typing_extensions import Self
from narwhals._polars.expr import PolarsExpr CurrentDecorator constructorclass requires: # noqa: N801
def __init__(self, *, min_version: tuple[int, ...], hint: str = "") -> None:
self._min_version: tuple[int, ...] = min_version
self._hint: str = hint
self._wrapped_name: str Usageclass DuckDBExpr:
@requires(min_version=(1, 3))
def is_first_distinct(self) -> Self: ...
class PolarsNamespace:
@requires(
min_version=(1, 0, 0), hint="Please use `col` for columns selection instead."
)
def nth(self, *indices: int) -> PolarsExpr: ... AlternativeWould be pretty easy to add support for multi- I also like that we can stay aligned with the Decorator constructorSee (651cf2f) Code block
class requires: # noqa: N801
@classmethod
def backend_version(cls, min_version: tuple[int, ...], /, hint: str = "") -> Self:
obj = cls.__new__(cls)
obj._min_version = min_version
obj._hint = hint
return obj Usageclass DuckDBExpr:
@requires.backend_version((1, 3))
def is_first_distinct(self) -> Self: ...
class PolarsNamespace:
@requires.backend_version(
(1, 0, 0), "Please use `col` for columns selection instead."
)
def nth(self, *indices: int) -> PolarsExpr: ... |
@requires
for backend method constraints@requires
for backend method constraints
I want to move all uses over to this style, but open to feedback in review π #2371 (comment)
@classmethod | ||
def backend_version(cls, minimum: tuple[int, ...], /, hint: str = "") -> Self: | ||
"""Method decorator for raising below a minimum `_backend_version`. | ||
Arguments: | ||
minimum: Minimum backend version. | ||
hint: Optional suggested alternative. | ||
Returns: | ||
An exception-raising decorator. | ||
""" | ||
obj = cls.__new__(cls) | ||
obj._min_version = minimum | ||
obj._hint = hint | ||
return obj |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to switch everything over to this style, see for comparison (#2371 (comment))
Also the one current use for coverage (0ac9595)
What type of PR is this? (check all applicable)
Related issues
Checklist
If you have comments or can explain your changes, please do so below
Adds a method decorator for consistent error messages on unsupported versions
Main use case is for enforcing a minimum version, e.g.:
Still have some other cases I wanna explore:
PolarsNamespace.nth
)Possible follow-ups
PandasLike*
.pivot
is a good example of multiple cases dependent on more than justbackend_version
:narwhals/narwhals/_pandas_like/dataframe.py
Lines 1032 to 1049 in d63ec65
Parameter combinations
I'd only want to include the version-based parameter restrictions on
@requires
:DuckDBLazyFrame.join(how="cross")
DuckDBExpr.broadcast(kind=ExprKind.AGGREGATION)
PolarsDataFrame.__array__(copy=...)
PolarsExpr.over(order_by=...)
It seems there are more blanket parameter restrictions, but they don't make sense as a
@requires
:DaskExpr.cum_*(reverse=True)
DaskExpr.rolling_*(ddof=2)
(or not1
)(Dask|DuckDB)Expr.quantile(interpolation="(nearest|higher|lower|midpoint)")
DuckDBLazyFrame.join_asof(strategy="nearest")
(DuckDB|SparkLike)Expr.fill_null(strategy=...)
(DuckDB|SparkLike)Expr.rank(method="(average|max|ordinal)")
DuckDBExprStringNamespace.to_datetime(format=None)
How to document this?
Like with
not_implemented
, we could mark the methods with runtime metadata. Then consume that in a script for something like https://narwhals-dev.github.io/narwhals/api-completeness/