diff --git a/biome.json b/biome.json index 96f8afcd..353ba7be 100644 --- a/biome.json +++ b/biome.json @@ -41,7 +41,8 @@ "noUnusedVariables": "warn" }, "nursery": { - "all": true + "all": true, + "noSecrets": "off" }, "performance": { "all": true, diff --git a/src/core/pd_array.ts b/src/core/pd_array.ts index de891d94..c6d43e7b 100644 --- a/src/core/pd_array.ts +++ b/src/core/pd_array.ts @@ -88,46 +88,35 @@ function classifyScalar(v: Scalar): "date" | "bigint" | "float" | "int" | "strin } function inferDtype(data: readonly Scalar[]): DtypeName { - let hasFloat = false; - let hasInt = false; - let hasString = false; - let hasBool = false; - let hasDate = false; - let hasBigInt = false; - + const kinds = new Set<"date" | "bigint" | "float" | "int" | "string" | "bool">(); for (const v of data) { const kind = classifyScalar(v); - if (kind === "date") { - hasDate = true; - } else if (kind === "bigint") { - hasBigInt = true; - } else if (kind === "float") { - hasFloat = true; - } else if (kind === "int") { - hasInt = true; - } else if (kind === "string") { - hasString = true; - } else if (kind === "bool") { - hasBool = true; + if (kind !== null) { + kinds.add(kind); } } + return resolveDtype(kinds); +} - if (hasDate) { +function resolveDtype( + kinds: ReadonlySet<"date" | "bigint" | "float" | "int" | "string" | "bool">, +): DtypeName { + if (kinds.has("date")) { return "datetime"; } - if (hasBigInt) { + if (kinds.has("bigint")) { return "int64"; } - if (hasFloat) { + if (kinds.has("float")) { return "float64"; } - if (hasInt && !hasString && !hasBool) { + if (kinds.has("int") && !kinds.has("string") && !kinds.has("bool")) { return "int64"; } - if (hasBool && !hasInt && !hasFloat && !hasString) { + if (kinds.has("bool") && !kinds.has("int") && !kinds.has("float") && !kinds.has("string")) { return "bool"; } - if (hasString) { + if (kinds.has("string")) { return "string"; } return "object"; diff --git a/src/core/series.ts b/src/core/series.ts index 29063e91..97fd75a9 100644 --- a/src/core/series.ts +++ b/src/core/series.ts @@ -777,8 +777,9 @@ export class Series { // When the same immutable _values array is sorted with the same ascending // direction, the sorted AoS buffer and nanBuf are identical. Restore them // directly and jump straight to the gather loop. - const cv = _cacheVals; - const isCacheHit = cv !== null && vals === cv && ascending === _cacheAscending; + // `vals === _cacheVals` short-circuits to false when _cacheVals is null + // (vals is never null), removing the need for an explicit null guard. + const isCacheHit = vals === _cacheVals && ascending === _cacheAscending; let finCount: number; let nanCount: number; @@ -977,7 +978,7 @@ export class Series { if (_permBuf.length < n) { _permBuf = new Array(n); _outBuf = new Array(n); - } else { + } else if (_permBuf.length > n) { // Truncate to exactly n so that [...perm] / [...outData] spreads only the // n elements we are about to write — not stale tail entries from a prior // larger sort call. diff --git a/tests/io/read_html.test.ts b/tests/io/read_html.test.ts index 370aae9c..98625d97 100644 --- a/tests/io/read_html.test.ts +++ b/tests/io/read_html.test.ts @@ -233,13 +233,13 @@ describe("readHtml – HTML entities", () => { }); test("decodes &#nn; decimal entities", () => { - const html = `
k
A
`; + const html = "
k
A
"; const [df] = readHtml(html, { converters: false }); expect(df!.col("k").toArray()[0]).toBe("A"); }); test("decodes &#xHH; hex entities", () => { - const html = `
k
B
`; + const html = "
k
B
"; const [df] = readHtml(html, { converters: false }); expect(df!.col("k").toArray()[0]).toBe("B"); }); diff --git a/tests/stats/style.test.ts b/tests/stats/style.test.ts index 341743d3..3675843b 100644 --- a/tests/stats/style.test.ts +++ b/tests/stats/style.test.ts @@ -391,7 +391,7 @@ describe("Styler.setCaption", () => { describe("Styler.hide", () => { test("hide index removes index column", () => { const df = makeNumericDf(); - const html = dataFrameStyle(df).hide(0).toHtml(); + const html = dataFrameStyle(df).hide(0).toHtml("x"); expect(html).not.toContain("r0"); expect(html).not.toContain("r1"); }); diff --git a/tests/xval/helpers.ts b/tests/xval/helpers.ts index 82de0380..0edb2783 100644 --- a/tests/xval/helpers.ts +++ b/tests/xval/helpers.ts @@ -86,14 +86,19 @@ function assertDataFrameMatchesSnapshot(actual: DataFrame, step: SnapshotStep): const expectedRows = expectMatrix(step); const expectedColumns = labelKeys(expectIndex(step.columns).values); const expectedIndex = labelKeys(expectIndex(step.index).values); + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect([...actual.shape]).toEqual([...(step.shape ?? [])]); + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect([...actual.columns.values]).toEqual(expectedColumns); + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect([...actual.index.values]).toEqual(expectedIndex); const actualRows = actual.toArray(); + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect(actualRows.length).toBe(expectedRows.length); for (let row = 0; row < expectedRows.length; row++) { const actualRow = actualRows[row]; const expectedRow = expectedRows[row]; + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect(actualRow?.length).toBe(expectedRow?.length); for (let col = 0; col < expectedColumns.length; col++) { assertJsonEqual( @@ -103,13 +108,16 @@ function assertDataFrameMatchesSnapshot(actual: DataFrame, step: SnapshotStep): ); } } + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect(Object.keys(step.dtypes ?? {}).length).toBe(expectedColumns.length); } function assertSeriesMatchesSnapshot(actual: Series, step: SnapshotStep): void { const expectedValues = expectVector(step); const expectedIndex = labelKeys(expectIndex(step.index).values); + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect([...actual.index.values]).toEqual(expectedIndex); + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect(actual.values.length).toBe(expectedValues.length); for (let pos = 0; pos < expectedValues.length; pos++) { assertJsonEqual( @@ -118,6 +126,7 @@ function assertSeriesMatchesSnapshot(actual: Series, step: SnapshotStep) `STEP ${step.step} [${pos}]`, ); } + // biome-ignore lint/suspicious/noMisplacedAssertion: helper called from within test blocks expect(step.dtype).toBeDefined(); } diff --git a/tests/xval/runner.test.ts b/tests/xval/runner.test.ts index 7c3572fa..ef75f6f5 100644 --- a/tests/xval/runner.test.ts +++ b/tests/xval/runner.test.ts @@ -39,25 +39,25 @@ function replayScenario(snapshot: ScenarioSnapshot): void { switch (snapshot.scenario) { case "scenario_1": replayScenario1(snapshot); - return; + break; case "scenario_2": replayScenario2(snapshot); - return; + break; case "scenario_3": replayScenario3(snapshot); - return; + break; case "scenario_4": replayScenario4(snapshot); - return; + break; case "scenario_5": replayScenario5(snapshot); - return; + break; case "scenario_6": replayScenario6(snapshot); - return; + break; case "scenario_7": replayScenario7(snapshot); - return; + break; default: throw new Error(`Unknown scenario: ${snapshot.scenario}`); }