From 2bb55d5974da7270fa1e5518e7ccce27f45d5d50 Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 25 Oct 2025 10:59:49 +0100 Subject: [PATCH 1/7] Fixed dataType.readonly --- polars/datatypes/datatype.ts | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/polars/datatypes/datatype.ts b/polars/datatypes/datatype.ts index 5315e285..2833d18a 100644 --- a/polars/datatypes/datatype.ts +++ b/polars/datatypes/datatype.ts @@ -2,9 +2,7 @@ import { Field } from "./field"; export abstract class DataType { declare readonly __dtype: Dtype; - get variant() { - return this.constructor.name as DataTypeName; - } + abstract readonly variant: DataTypeName; protected identity = "DataType"; protected get inner(): null | any[] { return null; @@ -166,66 +164,85 @@ export abstract class DataType { export class Null extends DataType<"Null"> { declare __dtype: "Null"; + readonly variant = "Null"; } export class Bool extends DataType<"Bool"> { declare __dtype: "Bool"; + readonly variant = "Bool"; } export class Int8 extends DataType<"Int8"> { declare __dtype: "Int8"; + readonly variant = "Int8"; } export class Int16 extends DataType<"Int16"> { declare __dtype: "Int16"; + readonly variant = "Int16"; } export class Int32 extends DataType<"Int32"> { declare __dtype: "Int32"; + readonly variant = "Int32"; } export class Int64 extends DataType<"Int64"> { declare __dtype: "Int64"; + readonly variant = "Int64"; } export class UInt8 extends DataType<"UInt8"> { declare __dtype: "UInt8"; + readonly variant = "UInt8"; } export class UInt16 extends DataType<"UInt16"> { declare __dtype: "UInt16"; + readonly variant = "UInt16"; } export class UInt32 extends DataType<"UInt32"> { declare __dtype: "UInt32"; + readonly variant = "UInt32"; } export class UInt64 extends DataType<"UInt64"> { declare __dtype: "UInt64"; + readonly variant = "UInt64"; } export class Float32 extends DataType<"Float32"> { declare __dtype: "Float32"; + readonly variant = "Float32"; } export class Float64 extends DataType<"Float64"> { declare __dtype: "Float64"; + readonly variant = "Float64"; } // biome-ignore lint/suspicious/noShadowRestrictedNames: Using Polars Date export class Date extends DataType<"Date"> { declare __dtype: "Date"; + readonly variant = "Date"; } export class Time extends DataType<"Time"> { declare __dtype: "Time"; + readonly variant = "Time"; } export class Object_ extends DataType<"Object"> { declare __dtype: "Object"; + readonly variant = "Object"; } export class Utf8 extends DataType<"Utf8"> { declare __dtype: "Utf8"; + readonly variant = "Utf8"; } // biome-ignore lint/suspicious/noShadowRestrictedNames: Using Polars String export class String extends DataType<"String"> { declare __dtype: "String"; + readonly variant = "String"; } export class Categorical extends DataType<"Categorical"> { declare __dtype: "Categorical"; + readonly variant = "Categorical"; } export class Decimal extends DataType<"Decimal"> { declare __dtype: "Decimal"; + readonly variant = "Decimal"; private precision: number | null; private scale: number | null; constructor(precision?: number, scale?: number) { @@ -263,6 +280,7 @@ export class Decimal extends DataType<"Decimal"> { */ export class Datetime extends DataType<"Datetime"> { declare __dtype: "Datetime"; + readonly variant = "Datetime"; constructor( private timeUnit: TimeUnit | "ms" | "ns" | "us" = "ms", private timeZone?: string | null, @@ -286,6 +304,7 @@ export class Datetime extends DataType<"Datetime"> { export class List extends DataType<"List"> { declare __dtype: "List"; + readonly variant = "List"; constructor(protected __inner: DataType) { super(); } @@ -302,6 +321,7 @@ export class List extends DataType<"List"> { export class FixedSizeList extends DataType<"FixedSizeList"> { declare __dtype: "FixedSizeList"; + readonly variant = "FixedSizeList"; constructor( protected __inner: DataType, protected listSize: number, @@ -336,6 +356,7 @@ export class FixedSizeList extends DataType<"FixedSizeList"> { export class Struct extends DataType<"Struct"> { declare __dtype: "Struct"; + readonly variant = "Struct"; private fields: Field[]; constructor( From 15694b674a7a66704b1dda08fe3de9346d9deb1b Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 25 Oct 2025 11:04:38 +0100 Subject: [PATCH 2/7] Added tests --- __tests__/datatypes.test.ts | 160 ++++++++++++++++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 __tests__/datatypes.test.ts diff --git a/__tests__/datatypes.test.ts b/__tests__/datatypes.test.ts new file mode 100644 index 00000000..5c0ab668 --- /dev/null +++ b/__tests__/datatypes.test.ts @@ -0,0 +1,160 @@ +import { DataType } from "@polars/datatypes"; + +describe("DataType variants", () => { + describe("Simple types", () => { + it("Null should have variant 'Null'", () => { + const dt = DataType.Null; + expect(dt.variant).toBe("Null"); + }); + + it("Bool should have variant 'Bool'", () => { + const dt = DataType.Bool; + expect(dt.variant).toBe("Bool"); + }); + + it("Int8 should have variant 'Int8'", () => { + const dt = DataType.Int8; + expect(dt.variant).toBe("Int8"); + }); + + it("Int16 should have variant 'Int16'", () => { + const dt = DataType.Int16; + expect(dt.variant).toBe("Int16"); + }); + + it("Int32 should have variant 'Int32'", () => { + const dt = DataType.Int32; + expect(dt.variant).toBe("Int32"); + }); + + it("Int64 should have variant 'Int64'", () => { + const dt = DataType.Int64; + expect(dt.variant).toBe("Int64"); + }); + + it("UInt8 should have variant 'UInt8'", () => { + const dt = DataType.UInt8; + expect(dt.variant).toBe("UInt8"); + }); + + it("UInt16 should have variant 'UInt16'", () => { + const dt = DataType.UInt16; + expect(dt.variant).toBe("UInt16"); + }); + + it("UInt32 should have variant 'UInt32'", () => { + const dt = DataType.UInt32; + expect(dt.variant).toBe("UInt32"); + }); + + it("UInt64 should have variant 'UInt64'", () => { + const dt = DataType.UInt64; + expect(dt.variant).toBe("UInt64"); + }); + + it("Float32 should have variant 'Float32'", () => { + const dt = DataType.Float32; + expect(dt.variant).toBe("Float32"); + }); + + it("Float64 should have variant 'Float64'", () => { + const dt = DataType.Float64; + expect(dt.variant).toBe("Float64"); + }); + + it("Date should have variant 'Date'", () => { + const dt = DataType.Date; + expect(dt.variant).toBe("Date"); + }); + + it("Time should have variant 'Time'", () => { + const dt = DataType.Time; + expect(dt.variant).toBe("Time"); + }); + + it("Object should have variant 'Object'", () => { + const dt = DataType.Object; + expect(dt.variant).toBe("Object"); + }); + + it("Utf8 should have variant 'Utf8'", () => { + const dt = DataType.Utf8; + expect(dt.variant).toBe("Utf8"); + }); + + it("String should have variant 'String'", () => { + const dt = DataType.String; + expect(dt.variant).toBe("String"); + }); + + it("Categorical should have variant 'Categorical'", () => { + const dt = DataType.Categorical; + expect(dt.variant).toBe("Categorical"); + }); + }); + + describe("Complex types", () => { + it("Decimal should have variant 'Decimal'", () => { + const dt = DataType.Decimal(); + expect(dt.variant).toBe("Decimal"); + }); + + it("Decimal with precision and scale should have variant 'Decimal'", () => { + const dt = DataType.Decimal(10, 2); + expect(dt.variant).toBe("Decimal"); + }); + + it("Datetime should have variant 'Datetime'", () => { + const dt = DataType.Datetime(); + expect(dt.variant).toBe("Datetime"); + }); + + it("Datetime with timeUnit should have variant 'Datetime'", () => { + const dt = DataType.Datetime("ms"); + expect(dt.variant).toBe("Datetime"); + }); + + it("Datetime with timeUnit and timeZone should have variant 'Datetime'", () => { + const dt = DataType.Datetime("ms", "America/New_York"); + expect(dt.variant).toBe("Datetime"); + }); + + it("List should have variant 'List'", () => { + const dt = DataType.List(DataType.Int32); + expect(dt.variant).toBe("List"); + }); + + it("FixedSizeList should have variant 'FixedSizeList'", () => { + const dt = DataType.FixedSizeList(DataType.Float64, 5); + expect(dt.variant).toBe("FixedSizeList"); + }); + + it("Struct should have variant 'Struct'", () => { + const dt = DataType.Struct({ + a: DataType.Int32, + b: DataType.Utf8, + }); + expect(dt.variant).toBe("Struct"); + }); + }); + + describe("Variant usage in equals", () => { + it("should use variant for type comparison", () => { + const dt1 = DataType.Int32; + const dt2 = DataType.Int32; + const dt3 = DataType.Int64; + + expect(dt1.equals(dt2)).toBe(true); + expect(dt1.equals(dt3)).toBe(false); + }); + + it("should use variant for complex type comparison", () => { + const dt1 = DataType.List(DataType.Int32); + const dt2 = DataType.List(DataType.Int32); + const dt3 = DataType.List(DataType.Float64); + + expect(dt1.equals(dt2)).toBe(true); + expect(dt1.equals(dt3)).toBe(false); + }); + }); +}); From 1cf1e8a84ad46bf6b2258b9b929f0173b76b78f7 Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 25 Oct 2025 11:08:21 +0100 Subject: [PATCH 3/7] Added type checking to precommit script --- package.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index f2337eb6..fb120888 100644 --- a/package.json +++ b/package.json @@ -50,8 +50,9 @@ "lint": "yarn lint:ts && yarn format:rs", "prepublishOnly": "napi prepublish -t npm", "test": "jest", + "type": "tsc --noEmit -p tsconfig.test.json", "version": "napi version", - "precommit": "yarn lint && yarn test" + "precommit": "yarn lint && yarn type && yarn test" }, "devDependencies": { "@biomejs/biome": "=2.2.4", From e7f5137ff38f581018279d4151469b6c04356076 Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 8 Nov 2025 14:03:55 +0000 Subject: [PATCH 4/7] Skip failling test not-related to the change --- .claude/settings.local.json | 13 +++++++++++++ __tests__/dataframe.test.ts | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json new file mode 100644 index 00000000..f789dc64 --- /dev/null +++ b/.claude/settings.local.json @@ -0,0 +1,13 @@ +{ + "permissions": { + "allow": [ + "Bash(yarn test:*)", + "mcp__serena__find_symbol", + "Bash(git log:*)", + "Bash(git stash:*)", + "Bash(git checkout:*)" + ], + "deny": [], + "ask": [] + } +} diff --git a/__tests__/dataframe.test.ts b/__tests__/dataframe.test.ts index 11c69aee..9a9cc0a1 100644 --- a/__tests__/dataframe.test.ts +++ b/__tests__/dataframe.test.ts @@ -2913,7 +2913,7 @@ describe("additional", () => { const actual = df.toRecords(); expect(actual).toEqual(rows); }); - test("upsample", () => { + test.skip("upsample", () => { const df = pl .DataFrame({ date: [ From 65719f7204f955325547c1e099cc9dca0e712d44 Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 8 Nov 2025 14:09:55 +0000 Subject: [PATCH 5/7] Ensure that strings have pl.String type in tests (not pl.Utf8) --- __tests__/io.test.ts | 2 +- __tests__/series.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/__tests__/io.test.ts b/__tests__/io.test.ts index a87952b3..77ee4aa3 100644 --- a/__tests__/io.test.ts +++ b/__tests__/io.test.ts @@ -220,7 +220,7 @@ describe("read:json", () => { ].join("\n"); const df = pl.readJSON(Buffer.from(json), { format: "lines" }); const actualCols = df.getColumns().map((x) => x.dtype); - expect(actualCols).toEqual([pl.Int64, pl.Utf8, pl.Null]); + expect(actualCols).toEqual([pl.Int64, pl.String, pl.Null]); }); }); diff --git a/__tests__/series.test.ts b/__tests__/series.test.ts index c5b6e973..0f1c0343 100644 --- a/__tests__/series.test.ts +++ b/__tests__/series.test.ts @@ -467,10 +467,10 @@ describe("series functions", () => { it.each` name | actual | expected - ${"dtype:Utf8"} | ${pl.Series(["foo"]).dtype} | ${pl.Utf8} + ${"dtype:String"} | ${pl.Series(["foo"]).dtype} | ${pl.String} ${"dtype:UInt64"} | ${pl.Series([1n]).dtype} | ${pl.UInt64} ${"dtype:Float64"} | ${pl.Series([1]).dtype} | ${pl.Float64} - ${"dtype"} | ${pl.Series(["foo"]).dtype} | ${pl.Utf8} + ${"dtype"} | ${pl.Series(["foo"]).dtype} | ${pl.String} ${"name"} | ${pl.Series("a", ["foo"]).name} | ${"a"} ${"length"} | ${pl.Series([1, 2, 3, 4]).length} | ${4} ${"abs"} | ${pl.Series([1, 2, -3]).abs()} | ${pl.Series([1, 2, 3])} From 5a608167900ac393c03dc7f273fcd2c3a837bc28 Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 8 Nov 2025 14:10:54 +0000 Subject: [PATCH 6/7] Removed debug files --- .claude/settings.local.json | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 .claude/settings.local.json diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index f789dc64..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(yarn test:*)", - "mcp__serena__find_symbol", - "Bash(git log:*)", - "Bash(git stash:*)", - "Bash(git checkout:*)" - ], - "deny": [], - "ask": [] - } -} From fb54c0a80cf26fa2f074b0527c9a4fbe4d18f9e5 Mon Sep 17 00:00:00 2001 From: roll Date: Sat, 8 Nov 2025 16:48:55 +0000 Subject: [PATCH 7/7] Unskipt upsample test --- __tests__/dataframe.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/__tests__/dataframe.test.ts b/__tests__/dataframe.test.ts index 9a9cc0a1..11c69aee 100644 --- a/__tests__/dataframe.test.ts +++ b/__tests__/dataframe.test.ts @@ -2913,7 +2913,7 @@ describe("additional", () => { const actual = df.toRecords(); expect(actual).toEqual(rows); }); - test.skip("upsample", () => { + test("upsample", () => { const df = pl .DataFrame({ date: [