@@ -16,7 +16,7 @@ use crate::obj::objbyteinner::PyBytesLike;
1616use crate :: obj:: objbytes:: PyBytesRef ;
1717use crate :: obj:: objint;
1818use crate :: obj:: objiter;
19- use crate :: obj:: objstr:: { self , PyStringRef } ;
19+ use crate :: obj:: objstr:: { self , PyString , PyStringRef } ;
2020use crate :: obj:: objtype:: { self , PyClassRef } ;
2121use crate :: pyobject:: {
2222 BufferProtocol , Either , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
@@ -812,12 +812,69 @@ fn buffered_writer_seekable(_self: PyObjectRef) -> bool {
812812 true
813813}
814814
815+ #[ derive( FromArgs ) ]
816+ struct TextIOWrapperArgs {
817+ #[ pyarg( positional_or_keyword, optional = false ) ]
818+ buffer : PyObjectRef ,
819+ #[ pyarg( positional_or_keyword, default = "None" ) ]
820+ encoding : Option < PyStringRef > ,
821+ #[ pyarg( positional_or_keyword, default = "None" ) ]
822+ errors : Option < PyStringRef > ,
823+ #[ pyarg( positional_or_keyword, default = "None" ) ]
824+ newline : Option < PyStringRef > ,
825+ }
826+
827+ impl TextIOWrapperArgs {
828+ fn validate_newline ( & self , vm : & VirtualMachine ) -> PyResult < ( ) > {
829+ if let Some ( pystr) = & self . newline {
830+ match pystr. as_str ( ) {
831+ "" | "\n " | "\r " | "\r \n " => Ok ( ( ) ) ,
832+ _ => {
833+ Err ( vm. new_value_error ( format ! ( "illegal newline value: '{}'" , pystr. repr( vm) ?) ) )
834+ }
835+ }
836+ } else {
837+ Ok ( ( ) )
838+ }
839+ }
840+ }
841+
815842fn text_io_wrapper_init (
816843 instance : PyObjectRef ,
817- buffer : PyObjectRef ,
844+ args : TextIOWrapperArgs ,
818845 vm : & VirtualMachine ,
819846) -> PyResult < ( ) > {
820- vm. set_attr ( & instance, "buffer" , buffer. clone ( ) ) ?;
847+ args. validate_newline ( vm) ?;
848+
849+ let mut encoding: Option < PyStringRef > = args. encoding . clone ( ) ;
850+ let mut self_encoding = None ; // TODO: Try os.device_encoding(fileno)
851+ if encoding. is_none ( ) && self_encoding. is_none ( ) {
852+ // TODO: locale module
853+ self_encoding = Some ( "utf-8" ) ;
854+ }
855+ if let Some ( self_encoding) = self_encoding {
856+ encoding = Some ( PyString :: from ( self_encoding) . into_ref ( vm) ) ;
857+ } else if let Some ( ref encoding) = encoding {
858+ self_encoding = Some ( encoding. as_str ( ) )
859+ } else {
860+ return Err ( vm. new_os_error ( "could not determine default encoding" . to_owned ( ) ) ) ;
861+ }
862+ let _ = encoding; // TODO: check codec
863+
864+ let errors = args
865+ . errors
866+ . map_or_else ( || vm. ctx . new_str ( "strict" ) , |o| o. into_object ( ) ) ;
867+
868+ // let readuniversal = args.newline.map_or_else(true, |s| s.as_str().is_empty());
869+
870+ vm. set_attr (
871+ & instance,
872+ "encoding" ,
873+ self_encoding. map_or_else ( || vm. get_none ( ) , |s| vm. ctx . new_str ( s) ) ,
874+ ) ?;
875+ vm. set_attr ( & instance, "errors" , errors) ?;
876+ vm. set_attr ( & instance, "buffer" , args. buffer . clone ( ) ) ?;
877+
821878 Ok ( ( ) )
822879}
823880
0 commit comments