@@ -16,7 +16,7 @@ use crate::obj::objbyteinner::PyBytesLike;
16
16
use crate :: obj:: objbytes:: PyBytesRef ;
17
17
use crate :: obj:: objint;
18
18
use crate :: obj:: objiter;
19
- use crate :: obj:: objstr:: { self , PyStringRef } ;
19
+ use crate :: obj:: objstr:: { self , PyString , PyStringRef } ;
20
20
use crate :: obj:: objtype:: { self , PyClassRef } ;
21
21
use crate :: pyobject:: {
22
22
BufferProtocol , Either , PyObjectRef , PyRef , PyResult , PyValue , TryFromObject ,
@@ -812,12 +812,69 @@ fn buffered_writer_seekable(_self: PyObjectRef) -> bool {
812
812
true
813
813
}
814
814
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
+
815
842
fn text_io_wrapper_init (
816
843
instance : PyObjectRef ,
817
- buffer : PyObjectRef ,
844
+ args : TextIOWrapperArgs ,
818
845
vm : & VirtualMachine ,
819
846
) -> 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
+
821
878
Ok ( ( ) )
822
879
}
823
880
0 commit comments