Merge branch 'nucoinha-patch-1' into dev · javascriptdata/danfojs@fe26a21 · GitHub | Latest TMZ Celebrity News & Gossip | Watch TMZ Live
Skip to content

Commit fe26a21

Browse files
committed
Merge branch 'nucoinha-patch-1' into dev
2 parents facc439 + c431bae commit fe26a21

File tree

4 files changed

+239
-82
lines changed

4 files changed

+239
-82
lines changed

src/danfojs-base/io/browser/io.csv.ts

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import Papa from 'papaparse'
2323
* hence all PapaParse options are supported.
2424
* @param options Configuration object. Supports all Papaparse parse config options.
2525
* @returns DataFrame containing the parsed CSV file.
26+
* @throws {Error} If file cannot be read or parsed
2627
* @example
2728
* ```
2829
* import { readCSV } from "danfojs-node"
@@ -48,16 +49,39 @@ import Papa from 'papaparse'
4849
const $readCSV = async (file: any, options?: CsvInputOptionsBrowser): Promise<DataFrame> => {
4950
const frameConfig = options?.frameConfig || {}
5051

51-
return new Promise(resolve => {
52+
return new Promise((resolve, reject) => {
53+
let hasError = false;
54+
5255
Papa.parse(file, {
5356
header: true,
5457
dynamicTyping: true,
5558
skipEmptyLines: 'greedy',
5659
...options,
60+
error: (error) => {
61+
hasError = true;
62+
reject(new Error(`Failed to parse CSV: ${error.message}`));
63+
},
5764
download: true,
58-
complete: results => {
59-
const df = new DataFrame(results.data, frameConfig);
60-
resolve(df);
65+
complete: (results) => {
66+
if (hasError) return; // Skip if error already occurred
67+
68+
if (!results.data || results.data.length === 0) {
69+
reject(new Error('No data found in CSV file'));
70+
return;
71+
}
72+
73+
if (results.errors && results.errors.length > 0) {
74+
reject(new Error(`CSV parsing errors: ${results.errors.map(e => e.message).join(', ')}`));
75+
return;
76+
}
77+
78+
try {
79+
const df = new DataFrame(results.data, frameConfig);
80+
resolve(df);
81+
} catch (error) {
82+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
83+
reject(new Error(`Failed to create DataFrame from CSV: ${errorMessage}`));
84+
}
6185
}
6286
});
6387
});
@@ -81,18 +105,35 @@ const $readCSV = async (file: any, options?: CsvInputOptionsBrowser): Promise<Da
81105
const $streamCSV = async (file: string, callback: (df: DataFrame) => void, options: CsvInputOptionsBrowser,): Promise<null> => {
82106
const frameConfig = options?.frameConfig || {}
83107

84-
return new Promise(resolve => {
108+
return new Promise((resolve, reject) => {
85109
let count = 0
110+
let hasError = false;
111+
86112
Papa.parse(file, {
87113
...options,
88114
dynamicTyping: true,
89115
header: true,
90116
download: true,
91117
step: results => {
92-
const df = new DataFrame([results.data], { ...frameConfig, index: [count++] });
93-
callback(df);
118+
if (hasError) return;
119+
try {
120+
const df = new DataFrame([results.data], { ...frameConfig, index: [count++] });
121+
callback(df);
122+
} catch (error) {
123+
hasError = true;
124+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
125+
reject(new Error(`Failed to process CSV chunk: ${errorMessage}`));
126+
}
127+
},
128+
complete: () => {
129+
if (!hasError) {
130+
resolve(null);
131+
}
94132
},
95-
complete: () => resolve(null)
133+
error: (error) => {
134+
hasError = true;
135+
reject(new Error(`Failed to parse CSV: ${error.message}`));
136+
}
96137
});
97138
});
98139
};

src/danfojs-base/io/node/io.csv.ts

Lines changed: 101 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import fs from 'fs'
2525
* hence all PapaParse options are supported.
2626
* @param options Configuration object. Supports all Papaparse parse config options.
2727
* @returns DataFrame containing the parsed CSV file.
28+
* @throws {Error} If file cannot be read or parsed
2829
* @example
2930
* ```
3031
* import { readCSV } from "danfojs-node"
@@ -52,6 +53,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
5253

5354
if (filePath.startsWith("http") || filePath.startsWith("https")) {
5455
return new Promise((resolve, reject) => {
56+
let hasError = false;
5557
const optionsWithDefaults = {
5658
header: true,
5759
dynamicTyping: true,
@@ -63,6 +65,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
6365
// reject any non-2xx status codes
6466
dataStream.on('response', (response: any) => {
6567
if (response.statusCode < 200 || response.statusCode >= 300) {
68+
hasError = true;
6669
reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
6770
}
6871
});
@@ -72,30 +75,73 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
7275

7376
const data: any = [];
7477
parseStream.on("data", (chunk: any) => {
75-
data.push(chunk);
78+
if (!hasError) {
79+
data.push(chunk);
80+
}
81+
});
82+
83+
parseStream.on("error", (error: any) => {
84+
hasError = true;
85+
reject(new Error(`Failed to parse CSV: ${error.message}`));
7686
});
7787

7888
parseStream.on("finish", () => {
79-
resolve(new DataFrame(data, frameConfig));
89+
if (hasError) return;
90+
91+
if (!data || data.length === 0) {
92+
reject(new Error('No data found in CSV file'));
93+
return;
94+
}
95+
96+
try {
97+
const df = new DataFrame(data, frameConfig);
98+
resolve(df);
99+
} catch (error) {
100+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
101+
reject(new Error(`Failed to create DataFrame: ${errorMessage}`));
102+
}
80103
});
81104
});
82105

83106
} else {
84107
return new Promise((resolve, reject) => {
85108
fs.access(filePath, fs.constants.F_OK, (err) => {
86109
if (err) {
87-
reject("ENOENT: no such file or directory");
110+
reject(new Error("ENOENT: no such file or directory"));
111+
return;
88112
}
89113

90114
const fileStream = fs.createReadStream(filePath)
115+
let hasError = false;
91116

92117
Papa.parse(fileStream, {
93118
header: true,
94119
dynamicTyping: true,
95120
...options,
121+
error: (error) => {
122+
hasError = true;
123+
reject(new Error(`Failed to parse CSV: ${error.message}`));
124+
},
96125
complete: results => {
97-
const df = new DataFrame(results.data, frameConfig);
98-
resolve(df);
126+
if (hasError) return;
127+
128+
if (!results.data || results.data.length === 0) {
129+
reject(new Error('No data found in CSV file'));
130+
return;
131+
}
132+
133+
if (results.errors && results.errors.length > 0) {
134+
reject(new Error(`CSV parsing errors: ${results.errors.map(e => e.message).join(', ')}`));
135+
return;
136+
}
137+
138+
try {
139+
const df = new DataFrame(results.data, frameConfig);
140+
resolve(df);
141+
} catch (error) {
142+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
143+
reject(new Error(`Failed to create DataFrame: ${errorMessage}`));
144+
}
99145
}
100146
});
101147
})
@@ -109,6 +155,7 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
109155
* hence all PapaParse options are supported.
110156
* @param callback Callback function to be called once the specifed rows are parsed into DataFrame.
111157
* @param options Configuration object. Supports all Papaparse parse config options.
158+
* @throws {Error} If file cannot be read or parsed
112159
* @example
113160
* ```
114161
* import { streamCSV } from "danfojs-node"
@@ -128,12 +175,14 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o
128175
...options,
129176
}
130177
return new Promise((resolve, reject) => {
131-
let count = 0
178+
let count = 0;
179+
let hasError = false;
132180
const dataStream = request.get(filePath);
133181

134182
// reject any non-2xx status codes
135183
dataStream.on('response', (response: any) => {
136184
if (response.statusCode < 200 || response.statusCode >= 300) {
185+
hasError = true;
137186
reject(new Error(`HTTP ${response.statusCode}: ${response.statusMessage}`));
138187
}
139188
});
@@ -142,35 +191,71 @@ const $streamCSV = async (filePath: string, callback: (df: DataFrame) => void, o
142191
dataStream.pipe(parseStream);
143192

144193
parseStream.on("data", (chunk: any) => {
145-
const df = new DataFrame([chunk], { ...frameConfig, index: [count++], });
146-
callback(df);
194+
if (hasError) return;
195+
try {
196+
const df = new DataFrame([chunk], { ...frameConfig, index: [count++] });
197+
callback(df);
198+
} catch (error) {
199+
hasError = true;
200+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
201+
reject(new Error(`Failed to process CSV chunk: ${errorMessage}`));
202+
}
147203
});
148204

149-
parseStream.on("finish", () => {
150-
resolve(null);
205+
parseStream.on("error", (error: any) => {
206+
hasError = true;
207+
reject(new Error(`Failed to parse CSV: ${error.message}`));
151208
});
152209

210+
parseStream.on("finish", () => {
211+
if (!hasError) {
212+
resolve(null);
213+
}
214+
});
153215
});
154216
} else {
155-
156217
return new Promise((resolve, reject) => {
157218
fs.access(filePath, fs.constants.F_OK, (err) => {
158219
if (err) {
159-
reject("ENOENT: no such file or directory");
220+
reject(new Error("ENOENT: no such file or directory"));
221+
return;
160222
}
161223

162224
const fileStream = fs.createReadStream(filePath)
225+
let hasError = false;
226+
let count = 0;
163227

164-
let count = 0
165228
Papa.parse(fileStream, {
166229
header: true,
167230
dynamicTyping: true,
168231
...options,
232+
error: (error) => {
233+
hasError = true;
234+
reject(new Error(`Failed to parse CSV: ${error.message}`));
235+
},
169236
step: results => {
170-
const df = new DataFrame([results.data], { ...frameConfig, index: [count++] });
171-
callback(df);
237+
if (hasError) return;
238+
239+
if (results.errors && results.errors.length > 0) {
240+
hasError = true;
241+
reject(new Error(`CSV parsing errors: ${results.errors.map(e => e.message).join(', ')}`));
242+
return;
243+
}
244+
245+
try {
246+
const df = new DataFrame([results.data], { ...frameConfig, index: [count++] });
247+
callback(df);
248+
} catch (error) {
249+
hasError = true;
250+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
251+
reject(new Error(`Failed to process CSV chunk: ${errorMessage}`));
252+
}
172253
},
173-
complete: () => resolve(null)
254+
complete: () => {
255+
if (!hasError) {
256+
resolve(null);
257+
}
258+
}
174259
});
175260
});
176261
});

src/danfojs-browser/tests/io/csv.reader.test.js

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,35 @@ describe("readCSV", function () {
6868
assert.deepEqual(df.values, values);
6969
});
7070

71+
it("Should throw error when reading non-existent remote file", async function () {
72+
const remoteFile = "https://raw.githubusercontent.com/javascriptdata/danfojs/dev/nonexistent.csv";
73+
try {
74+
await dfd.readCSV(remoteFile);
75+
assert.fail("Should have thrown an error");
76+
} catch (error) {
77+
assert.ok(error instanceof Error);
78+
}
79+
});
80+
81+
it("Should throw error when reading malformed CSV", async function () {
82+
const malformedCSV = new File([ "a,b,c\n1,2\n3,4,5,6" ], "malformed.csv", { type: "text/csv" });
83+
try {
84+
await dfd.readCSV(malformedCSV);
85+
assert.fail("Should have thrown an error");
86+
} catch (error) {
87+
assert.ok(error instanceof Error);
88+
}
89+
});
90+
91+
it("Should throw error when reading invalid file type", async function () {
92+
const invalidFile = new File([ "not a csv" ], "test.txt", { type: "text/plain" });
93+
try {
94+
await dfd.readCSV(invalidFile);
95+
assert.fail("Should have thrown an error");
96+
} catch (error) {
97+
assert.ok(error instanceof Error);
98+
}
99+
});
71100
});
72101

73102
// describe("streamCSV", function () {
@@ -114,5 +143,4 @@ describe("toCSV", function () {
114143
let df = new dfd.Series(data);
115144
assert.deepEqual(dfd.toCSV(df, { sep: "+", download: false }), `1+2+3+4+5+6+7+8+9+10+11+12`);
116145
});
117-
118146
});

0 commit comments

Comments
 (0)

TMZ Celebrity News – Breaking Stories, Videos & Gossip

Looking for the latest TMZ celebrity news? You've come to the right place. From shocking Hollywood scandals to exclusive videos, TMZ delivers it all in real time.

Whether it’s a red carpet slip-up, a viral paparazzi moment, or a legal drama involving your favorite stars, TMZ news is always first to break the story. Stay in the loop with daily updates, insider tips, and jaw-dropping photos.

🎥 Watch TMZ Live

TMZ Live brings you daily celebrity news and interviews straight from the TMZ newsroom. Don’t miss a beat—watch now and see what’s trending in Hollywood.