-
Notifications
You must be signed in to change notification settings - Fork 205
feat: Adds Compliant(When|Then)
#2261
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
Changes from 6 commits
f6deab5
db5c25f
3486f55
f1689e7
de3ccad
8d671b2
1ac7daa
9e7d848
ebbefa8
6767c38
396605e
5a22284
c002fcf
3b81fbe
f2149e6
32d2741
541f532
6183be7
724ff96
a9a6ccd
5adda67
9c9ea48
cc5cce1
b0b1a05
9c680dc
ededf10
2e38646
9c85a3f
ed2e7e8
07f51da
a339a5e
9632f3a
328bb43
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import sys | ||
| from typing import TYPE_CHECKING | ||
| from typing import Any | ||
| from typing import Callable | ||
| from typing import Sequence | ||
| from typing import cast | ||
|
|
||
| from narwhals._compliant.expr import CompliantExpr | ||
| from narwhals._compliant.typing import CompliantExprT | ||
| from narwhals._compliant.typing import CompliantFrameT | ||
| from narwhals._compliant.typing import CompliantSeriesOrNativeExprT | ||
|
|
||
| if TYPE_CHECKING: | ||
| from typing_extensions import Self | ||
| from typing_extensions import TypeAlias | ||
|
|
||
| from narwhals.utils import Implementation | ||
| from narwhals.utils import Version | ||
| from narwhals.utils import _FullContext | ||
|
|
||
| if not TYPE_CHECKING: # pragma: no cover | ||
| if sys.version_info >= (3, 9): | ||
| from typing import Protocol as Protocol38 | ||
| else: | ||
| from typing import Generic as Protocol38 | ||
| else: # pragma: no cover | ||
| # TODO @dangotbanned: Remove after dropping `3.8` (#2084) | ||
| # - https://github.com/narwhals-dev/narwhals/pull/2064#discussion_r1965921386 | ||
| from typing import Protocol as Protocol38 | ||
|
|
||
| _Scalar: TypeAlias = Any | ||
|
|
||
|
|
||
| class CompliantWhen( | ||
| Protocol38[CompliantFrameT, CompliantSeriesOrNativeExprT, CompliantExprT] | ||
| ): | ||
| _condition: CompliantExprT | ||
| _then_value: CompliantExprT | CompliantSeriesOrNativeExprT | _Scalar | ||
| _otherwise_value: CompliantExprT | CompliantSeriesOrNativeExprT | _Scalar | ||
| _implementation: Implementation | ||
| _backend_version: tuple[int, ...] | ||
| _version: Version | ||
|
|
||
| @property | ||
| def _then( | ||
| self, | ||
| ) -> type[ | ||
| CompliantThen[CompliantFrameT, CompliantSeriesOrNativeExprT, CompliantExprT] | ||
| ]: ... | ||
|
|
||
| def __call__( | ||
| self, compliant_frame: CompliantFrameT, / | ||
| ) -> Sequence[CompliantSeriesOrNativeExprT]: ... | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODOTry to find common parts and split up their implementation
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will allow most of
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wasn't expecting I'd be able to reduce it down this much ...
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Resolved from (cc5cce1) onwards
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note Mentioned in (b0b1a05) that I'm tentative on Happy to merge as-is, but its just the least-bad idea I had so far |
||
|
|
||
| def then( | ||
| self, value: CompliantExprT | CompliantSeriesOrNativeExprT | _Scalar, / | ||
| ) -> CompliantThen[CompliantFrameT, CompliantSeriesOrNativeExprT, CompliantExprT]: | ||
| return self._then.from_when(self, value) | ||
|
|
||
| def __init__(self, condition: CompliantExprT, /, *, context: _FullContext) -> None: | ||
| self._condition = condition | ||
| self._then_value = None | ||
| self._otherwise_value = None | ||
| self._implementation = context._implementation | ||
| self._backend_version = context._backend_version | ||
| self._version = context._version | ||
|
dangotbanned marked this conversation as resolved.
Outdated
|
||
|
|
||
|
|
||
| class CompliantThen( | ||
| CompliantExpr[CompliantFrameT, CompliantSeriesOrNativeExprT], | ||
| Protocol38[CompliantFrameT, CompliantSeriesOrNativeExprT, CompliantExprT], | ||
| ): | ||
| _call: Callable[[CompliantFrameT], Sequence[CompliantSeriesOrNativeExprT]] | ||
| _when: CompliantWhen[CompliantFrameT, CompliantSeriesOrNativeExprT, CompliantExprT] | ||
|
dangotbanned marked this conversation as resolved.
Outdated
|
||
| _function_name: str | ||
| _implementation: Implementation | ||
| _backend_version: tuple[int, ...] | ||
| _version: Version | ||
| _call_kwargs: dict[str, Any] | ||
|
|
||
| @classmethod | ||
| def from_when( | ||
| cls, | ||
| when: CompliantWhen[ | ||
| CompliantFrameT, CompliantSeriesOrNativeExprT, CompliantExprT | ||
| ], | ||
| then_value: CompliantExprT | CompliantSeriesOrNativeExprT | _Scalar, | ||
| /, | ||
| ) -> Self: | ||
| when._then_value = then_value | ||
| obj = cls.__new__(cls) | ||
| obj._call = when | ||
| obj._when = when | ||
| obj._depth = 0 | ||
| obj._function_name = "whenthen" | ||
| obj._evaluate_output_names = getattr( | ||
| then_value, "_evaluate_output_names", lambda _df: ["literal"] | ||
| ) | ||
| obj._alias_output_names = getattr(then_value, "_alias_output_names", None) | ||
| obj._implementation = when._implementation | ||
| obj._backend_version = when._backend_version | ||
| obj._version = when._version | ||
| obj._call_kwargs = {} | ||
| return obj | ||
|
Comment on lines
+93
to
+114
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Important Probably going to try something like this for Will wait for (#2266) to land first though |
||
|
|
||
| def otherwise( | ||
| self, value: CompliantExprT | CompliantSeriesOrNativeExprT | _Scalar, / | ||
| ) -> CompliantExprT: | ||
| self._when._otherwise_value = value | ||
| self._function_name = "whenotherwise" | ||
| return cast("CompliantExprT", self) | ||
Uh oh!
There was an error while loading. Please reload this page.
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.
Before anyone asks - yes this is a fully working implementation π
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.
wow!