Skip to content

Commit 3d10b11

Browse files
committed
WIP: Narwhals support
1 parent 7fc5ff5 commit 3d10b11

20 files changed

Lines changed: 881 additions & 112 deletions

File tree

‎.cargo/config.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ ATTRS_TEST_PATH = { value = "pyrefly/lib/test/attrs/third-party", relative = tru
1010
CINDERX_FIXTURES_PATH = { value = "pyrefly/lib/test/cinderx/fixtures", relative = true }
1111
MARSHMALLOW_TEST_PATH = { value = "pyrefly/lib/test/marshmallow/third-party", relative = true }
1212
POLARS_TEST_PATH = { value = "pyrefly/lib/test/polars/third-party", relative = true }
13+
NARWHALS_TEST_PATH = { value = "pyrefly/lib/test/narwhals/third-party", relative = true }
1314
GLEAN_SNAPSHOTS_PATH = { value = "pyrefly/lib/report/glean/snapshots", relative = true }
1415
COVERAGE_TEST_PATH = { value = "pyrefly/lib/test/coverage/test_files", relative = true }
1516
STUBGEN_TEST_PATH = { value = "pyrefly/lib/test/stubgen", relative = true }

‎crates/pyrefly_types/src/data_frame.rs‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,16 @@ impl SchemaCompleteness {
3939
)]
4040
pub enum DataFrameKind {
4141
Polars,
42+
Narwhals,
4243
Pandas,
4344
}
4445

46+
impl DataFrameKind {
47+
pub fn is_polars_api(self) -> bool {
48+
matches!(self, Self::Polars | Self::Narwhals)
49+
}
50+
}
51+
4552
/// Whether a schema is inferred or declared by an explicit annotation.
4653
#[derive(
4754
Debug, PartialOrd, Ord, Clone, Copy, Eq, PartialEq, Hash, Visit, VisitMut, TypeEq

‎pyrefly/lib/alt/expr.rs‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use pyrefly_python::dunder;
1818
use pyrefly_python::module_name::ModuleName;
1919
use pyrefly_python::nesting_context::NestingContext;
2020
use pyrefly_python::short_identifier::ShortIdentifier;
21-
use pyrefly_types::data_frame::DataFrameKind;
2221
use pyrefly_types::dimension::Int;
2322
use pyrefly_types::dimension::canonicalize;
2423
use pyrefly_types::dimension::gradual_size;
@@ -88,7 +87,7 @@ use crate::alt::answers_solver::TypeCheckOptions;
8887
use crate::alt::callable::CallArg;
8988
use crate::alt::class::typed_dict::TypedDictErrorKind;
9089
use crate::alt::nn_module_specials::is_nn_module_dict;
91-
use crate::alt::polars_specials::is_polars_series;
90+
use crate::alt::polars_specials::is_polars_api_series;
9291
use crate::alt::regex::RegexValidationError;
9392
use crate::alt::regex::validate_pattern;
9493
use crate::alt::shape_extension::is_int_tuple_bound;
@@ -3833,7 +3832,7 @@ impl<'ctx, 'answer, Ans: LookupAnswer> AnswersSolver<'ctx, 'answer, Ans> {
38333832
),
38343833
Type::DataFrame(schema) => {
38353834
if let Expr::List(ExprList { elts, .. }) = slice
3836-
&& schema.kind == DataFrameKind::Polars
3835+
&& schema.kind.is_polars_api()
38373836
{
38383837
if elts.is_empty() {
38393838
return Type::DataFrame(schema);
@@ -3849,7 +3848,7 @@ impl<'ctx, 'answer, Ans: LookupAnswer> AnswersSolver<'ctx, 'answer, Ans> {
38493848
&& let Some(name) = self.polars_column_name(slice)
38503849
{
38513850
match schema.columns.iter().find(|(c, _)| **c == name) {
3852-
Some((_, dtype)) if schema.kind == DataFrameKind::Polars => {
3851+
Some((_, dtype)) if schema.kind.is_polars_api() => {
38533852
column_dtype = Some(dtype.clone());
38543853
}
38553854
Some(_) => {}
@@ -3876,7 +3875,7 @@ impl<'ctx, 'answer, Ans: LookupAnswer> AnswersSolver<'ctx, 'answer, Ans> {
38763875
// Preserve the stub's Series class when attaching an element dtype.
38773876
match (column_dtype, result) {
38783877
(Some(dtype), Type::ClassType(cls))
3879-
if is_polars_series(cls.class_object()) =>
3878+
if is_polars_api_series(cls.class_object()) =>
38803879
{
38813880
SeriesSchema {
38823881
underlying: cls,

0 commit comments

Comments
 (0)