Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc431bae

Browse files
committed
make error handler on read csv more robust
1 parent9dc7681 commitc431bae

File tree

4 files changed

+237
-82
lines changed

4 files changed

+237
-82
lines changed

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

Lines changed: 47 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"
@@ -49,16 +50,38 @@ const $readCSV = async (file: any, options?: CsvInputOptionsBrowser): Promise<Da
4950
constframeConfig=options?.frameConfig||{}
5051

5152
returnnewPromise((resolve,reject)=>{
53+
lethasError=false;
54+
5255
Papa.parse(file,{
5356
header:true,
5457
dynamicTyping:true,
5558
skipEmptyLines:'greedy',
5659
...options,
57-
error:(error,file)=>reject(error,file),
60+
error:(error)=>{
61+
hasError=true;
62+
reject(newError(`Failed to parse CSV:${error.message}`));
63+
},
5864
download:true,
59-
complete:results=>{
60-
constdf=newDataFrame(results.data,frameConfig);
61-
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(newError('No data found in CSV file'));
70+
return;
71+
}
72+
73+
if(results.errors&&results.errors.length>0){
74+
reject(newError(`CSV parsing errors:${results.errors.map(e=>e.message).join(', ')}`));
75+
return;
76+
}
77+
78+
try{
79+
constdf=newDataFrame(results.data,frameConfig);
80+
resolve(df);
81+
}catch(error){
82+
consterrorMessage=errorinstanceofError ?error.message :'Unknown error occurred';
83+
reject(newError(`Failed to create DataFrame from CSV:${errorMessage}`));
84+
}
6285
}
6386
});
6487
});
@@ -84,17 +107,33 @@ const $streamCSV = async (file: string, callback: (df: DataFrame) => void, optio
84107

85108
returnnewPromise((resolve,reject)=>{
86109
letcount=0
110+
lethasError=false;
111+
87112
Papa.parse(file,{
88113
...options,
89114
dynamicTyping:true,
90115
header:true,
91116
download:true,
92117
step:results=>{
93-
constdf=newDataFrame([results.data],{ ...frameConfig,index:[count++]});
94-
callback(df);
118+
if(hasError)return;
119+
try{
120+
constdf=newDataFrame([results.data],{ ...frameConfig,index:[count++]});
121+
callback(df);
122+
}catch(error){
123+
hasError=true;
124+
consterrorMessage=errorinstanceofError ?error.message :'Unknown error occurred';
125+
reject(newError(`Failed to process CSV chunk:${errorMessage}`));
126+
}
127+
},
128+
complete:()=>{
129+
if(!hasError){
130+
resolve(null);
131+
}
95132
},
96-
complete:()=>resolve(null),
97-
error:(error,file)=>reject(error,file)
133+
error:(error)=>{
134+
hasError=true;
135+
reject(newError(`Failed to parse CSV:${error.message}`));
136+
}
98137
});
99138
});
100139
};

‎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
returnnewPromise((resolve,reject)=>{
56+
lethasError=false;
5557
constoptionsWithDefaults={
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(newError(`HTTP${response.statusCode}:${response.statusMessage}`));
6770
}
6871
});
@@ -72,30 +75,73 @@ const $readCSV = async (filePath: string, options?: CsvInputOptionsNode): Promis
7275

7376
constdata: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(newError(`Failed to parse CSV:${error.message}`));
7686
});
7787

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

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

90114
constfileStream=fs.createReadStream(filePath)
115+
lethasError=false;
91116

92117
Papa.parse(fileStream,{
93118
header:true,
94119
dynamicTyping:true,
95120
...options,
121+
error:(error)=>{
122+
hasError=true;
123+
reject(newError(`Failed to parse CSV:${error.message}`));
124+
},
96125
complete:results=>{
97-
constdf=newDataFrame(results.data,frameConfig);
98-
resolve(df);
126+
if(hasError)return;
127+
128+
if(!results.data||results.data.length===0){
129+
reject(newError('No data found in CSV file'));
130+
return;
131+
}
132+
133+
if(results.errors&&results.errors.length>0){
134+
reject(newError(`CSV parsing errors:${results.errors.map(e=>e.message).join(', ')}`));
135+
return;
136+
}
137+
138+
try{
139+
constdf=newDataFrame(results.data,frameConfig);
140+
resolve(df);
141+
}catch(error){
142+
consterrorMessage=errorinstanceofError ?error.message :'Unknown error occurred';
143+
reject(newError(`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
returnnewPromise((resolve,reject)=>{
131-
letcount=0
178+
letcount=0;
179+
lethasError=false;
132180
constdataStream=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(newError(`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-
constdf=newDataFrame([chunk],{ ...frameConfig,index:[count++],});
146-
callback(df);
194+
if(hasError)return;
195+
try{
196+
constdf=newDataFrame([chunk],{ ...frameConfig,index:[count++]});
197+
callback(df);
198+
}catch(error){
199+
hasError=true;
200+
consterrorMessage=errorinstanceofError ?error.message :'Unknown error occurred';
201+
reject(newError(`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(newError(`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
returnnewPromise((resolve,reject)=>{
157218
fs.access(filePath,fs.constants.F_OK,(err)=>{
158219
if(err){
159-
reject("ENOENT: no such file or directory");
220+
reject(newError("ENOENT: no such file or directory"));
221+
return;
160222
}
161223

162224
constfileStream=fs.createReadStream(filePath)
225+
lethasError=false;
226+
letcount=0;
163227

164-
letcount=0
165228
Papa.parse(fileStream,{
166229
header:true,
167230
dynamicTyping:true,
168231
...options,
232+
error:(error)=>{
233+
hasError=true;
234+
reject(newError(`Failed to parse CSV:${error.message}`));
235+
},
169236
step:results=>{
170-
constdf=newDataFrame([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(newError(`CSV parsing errors:${results.errors.map(e=>e.message).join(', ')}`));
242+
return;
243+
}
244+
245+
try{
246+
constdf=newDataFrame([results.data],{ ...frameConfig,index:[count++]});
247+
callback(df);
248+
}catch(error){
249+
hasError=true;
250+
consterrorMessage=errorinstanceofError ?error.message :'Unknown error occurred';
251+
reject(newError(`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",asyncfunction(){
72+
constremoteFile="https://raw.githubusercontent.com/javascriptdata/danfojs/dev/nonexistent.csv";
73+
try{
74+
awaitdfd.readCSV(remoteFile);
75+
assert.fail("Should have thrown an error");
76+
}catch(error){
77+
assert.ok(errorinstanceofError);
78+
}
79+
});
80+
81+
it("Should throw error when reading malformed CSV",asyncfunction(){
82+
constmalformedCSV=newFile(["a,b,c\n1,2\n3,4,5,6"],"malformed.csv",{type:"text/csv"});
83+
try{
84+
awaitdfd.readCSV(malformedCSV);
85+
assert.fail("Should have thrown an error");
86+
}catch(error){
87+
assert.ok(errorinstanceofError);
88+
}
89+
});
90+
91+
it("Should throw error when reading invalid file type",asyncfunction(){
92+
constinvalidFile=newFile(["not a csv"],"test.txt",{type:"text/plain"});
93+
try{
94+
awaitdfd.readCSV(invalidFile);
95+
assert.fail("Should have thrown an error");
96+
}catch(error){
97+
assert.ok(errorinstanceofError);
98+
}
99+
});
71100
});
72101

73102
// describe("streamCSV", function () {
@@ -114,5 +143,4 @@ describe("toCSV", function () {
114143
letdf=newdfd.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)

[8]ページ先頭

©2009-2025 Movatter.jp