@@ -243,49 +243,87 @@ fn buffered_writer_write(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult
243
243
244
244
}
245
245
246
+ fn text_io_wrapper_init ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
247
+ arg_check ! (
248
+ vm,
249
+ args,
250
+ required = [ ( text_io_wrapper, None ) , ( buffer, None ) ]
251
+ ) ;
252
+
253
+ vm. ctx . set_attr ( & text_io_wrapper, "buffer" , buffer. clone ( ) ) ;
254
+ Ok ( vm. get_none ( ) )
255
+ }
256
+
257
+
258
+ fn text_io_base_read ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
259
+ arg_check ! (
260
+ vm,
261
+ args,
262
+ required = [ ( text_io_base, None ) ]
263
+ ) ;
264
+
265
+ let raw = vm. ctx . get_attr ( & text_io_base, "buffer" ) . unwrap ( ) ;
266
+ let read = vm. get_method ( raw. clone ( ) , & "read" . to_string ( ) ) ;
267
+
268
+ //TODO: bytes to string
269
+ vm. invoke ( read. unwrap ( ) , PyFuncArgs :: default ( ) )
270
+ }
271
+
272
+
246
273
pub fn io_open ( vm : & mut VirtualMachine , args : PyFuncArgs ) -> PyResult {
247
274
arg_check ! (
248
275
vm,
249
276
args,
250
- required = [ ( file, Some ( vm. ctx. str_type( ) ) ) , ( mode, Some ( vm. ctx. str_type( ) ) ) ]
277
+ required = [ ( _file, Some ( vm. ctx. str_type( ) ) ) ] ,
278
+ optional = [ ( mode, Some ( vm. ctx. str_type( ) ) ) ]
251
279
) ;
252
280
253
281
let module = mk_module ( & vm. ctx ) ;
254
282
255
283
//mode is optional: 'rt' is the default mode (open from reading text)
256
- //To start we construct a FileIO (subclass of RawIOBase)
284
+ let rust_mode = if let Some ( m) = mode {
285
+ objstr:: get_value ( m)
286
+ } else {
287
+ "rt" . to_string ( )
288
+ } ;
289
+
290
+ //Class objects (potentially) consumed by io.open
291
+ //RawIO: FileIO
292
+ //Buffered: BufferedWriter, BufferedReader
293
+ //Text: TextIOWrapper
257
294
let file_io_class = vm. ctx . get_attr ( & module, "FileIO" ) . unwrap ( ) ;
258
295
let buffered_writer_class = vm. ctx . get_attr ( & module, "BufferedWriter" ) . unwrap ( ) ;
259
296
let buffered_reader_class = vm. ctx . get_attr ( & module, "BufferedReader" ) . unwrap ( ) ;
297
+ let text_io_wrapper_class = vm. ctx . get_attr ( & module, "TextIOWrapper" ) . unwrap ( ) ;
260
298
261
- //instantiate raw fileio
299
+ //Construct a FileIO (subclass of RawIOBase)
300
+ //This is subsequently consumed by a Buffered Class.
262
301
let file_io = vm. invoke ( file_io_class, args. clone ( ) ) . unwrap ( ) ;
263
302
264
- //This is subsequently consumed by a Buffered_class of type depending
265
- //operation in the mode. i.e:
266
- let rust_mode = objstr:: get_value ( mode) ;
267
-
268
- // updating => PyBufferedRandom
303
+ //Create Buffered class to consume FileIO. The type of buffered class depends on
304
+ //the operation in the mode.
305
+ //There are 3 possible classes here, each inheriting from the RawBaseIO
269
306
// creating || writing || appending => BufferedWriter
270
307
let buffered = if rust_mode. contains ( "w" ) {
271
- // vm.new_not_implemented_error("Writes are not yet implemented".to_string());
272
308
vm. invoke ( buffered_writer_class, PyFuncArgs :: new ( vec ! [ file_io. clone( ) ] , vec ! [ ] ) )
273
309
// reading => BufferedReader
274
310
} else {
275
311
vm. invoke ( buffered_reader_class, PyFuncArgs :: new ( vec ! [ file_io. clone( ) ] , vec ! [ ] ) )
312
+ //TODO: updating => PyBufferedRandom
276
313
} ;
277
314
278
- buffered
315
+ if rust_mode. contains ( "t" ) {
316
+ //If the mode is text this buffer type is consumed on construction of
317
+ //a TextIOWrapper which is subsequently returned.
318
+ vm. invoke ( text_io_wrapper_class, PyFuncArgs :: new ( vec ! [ buffered. unwrap( ) ] , vec ! [ ] ) )
319
+ } else {
279
320
// If the mode is binary this Buffered class is returned directly at
280
321
// this point.
281
322
//For Buffered class construct "raw" IO class e.g. FileIO and pass this into corresponding field
282
-
283
- //If the mode is text this buffer type is consumed on construction of
284
- //a TextIOWrapper which is subsequently returned.
285
- // Ok(vm.get_none())
323
+ buffered
324
+ }
286
325
}
287
326
288
-
289
327
pub fn mk_module ( ctx : & PyContext ) -> PyObjectRef {
290
328
let py_mod = ctx. new_module ( & "io" . to_string ( ) , ctx. new_scope ( None ) ) ;
291
329
ctx. set_attr ( & py_mod, "open" , ctx. new_rustfunc ( io_open) ) ;
@@ -301,7 +339,9 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
301
339
ctx. set_attr ( & buffered_io_base, "__init__" , ctx. new_rustfunc ( buffered_io_base_init) ) ;
302
340
ctx. set_attr ( & py_mod, "BufferedIOBase" , buffered_io_base. clone ( ) ) ;
303
341
342
+ //TextIO Base has no public constructor
304
343
let text_io_base = ctx. new_class ( "TextIOBase" , io_base. clone ( ) ) ;
344
+ ctx. set_attr ( & text_io_base, "read" , ctx. new_rustfunc ( text_io_base_read) ) ;
305
345
ctx. set_attr ( & py_mod, "TextIOBase" , text_io_base. clone ( ) ) ;
306
346
307
347
// RawBaseIO Subclasses
@@ -323,7 +363,8 @@ pub fn mk_module(ctx: &PyContext) -> PyObjectRef {
323
363
ctx. set_attr ( & py_mod, "BufferedWriter" , buffered_writer. clone ( ) ) ;
324
364
325
365
//TextIOBase Subclass
326
- let text_io_wrapper = ctx. new_class ( "TextIOWrapper" , ctx. object ( ) ) ;
366
+ let text_io_wrapper = ctx. new_class ( "TextIOWrapper" , text_io_base. clone ( ) ) ;
367
+ ctx. set_attr ( & text_io_wrapper, "__init__" , ctx. new_rustfunc ( text_io_wrapper_init) ) ;
327
368
ctx. set_attr ( & py_mod, "TextIOWrapper" , text_io_wrapper. clone ( ) ) ;
328
369
329
370
// BytesIO: in-memory bytes
0 commit comments