1+ use num_traits:: ToPrimitive ;
12use std:: { env, mem, path} ;
23
34use crate :: frame:: FrameRef ;
45use crate :: function:: { Args , OptionalArg , PyFuncArgs } ;
56use crate :: obj:: objstr:: PyStringRef ;
7+ use crate :: obj:: objtype:: PyClassRef ;
68use crate :: pyobject:: { IntoPyObject , ItemProtocol , PyClassImpl , PyContext , PyObjectRef , PyResult } ;
79use crate :: vm:: { PySettings , VirtualMachine } ;
810use crate :: { builtins, exceptions, py_io, version} ;
@@ -26,7 +28,11 @@ fn argv(vm: &VirtualMachine) -> PyObjectRef {
2628
2729fn executable ( ctx : & PyContext ) -> PyObjectRef {
2830 if let Some ( exec_path) = env:: args ( ) . next ( ) {
29- if path:: Path :: new ( & exec_path) . is_absolute ( ) {
31+ let path = path:: Path :: new ( & exec_path) ;
32+ if !path. exists ( ) {
33+ return ctx. new_str ( "" ) ;
34+ }
35+ if path. is_absolute ( ) {
3036 return ctx. new_str ( exec_path) ;
3137 }
3238 if let Ok ( dir) = env:: current_dir ( ) {
@@ -67,50 +73,50 @@ fn getframe(offset: OptionalArg<usize>, vm: &VirtualMachine) -> PyResult<FrameRe
6773#[ derive( Default , Debug ) ]
6874struct SysFlags {
6975 /// -d
70- debug : bool ,
76+ debug : u8 ,
7177 /// -i
72- inspect : bool ,
78+ inspect : u8 ,
7379 /// -i
74- interactive : bool ,
80+ interactive : u8 ,
7581 /// -O or -OO
7682 optimize : u8 ,
7783 /// -B
78- dont_write_bytecode : bool ,
84+ dont_write_bytecode : u8 ,
7985 /// -s
80- no_user_site : bool ,
86+ no_user_site : u8 ,
8187 /// -S
82- no_site : bool ,
88+ no_site : u8 ,
8389 /// -E
84- ignore_environment : bool ,
90+ ignore_environment : u8 ,
8591 /// -v
8692 verbose : u8 ,
8793 /// -b
88- bytes_warning : bool ,
94+ bytes_warning : u8 ,
8995 /// -q
90- quiet : bool ,
96+ quiet : u8 ,
9197 /// -R
92- hash_randomization : bool ,
98+ hash_randomization : u8 ,
9399 /// -I
94- isolated : bool ,
100+ isolated : u8 ,
95101 /// -X dev
96102 dev_mode : bool ,
97103 /// -X utf8
98- utf8_mode : bool ,
104+ utf8_mode : u8 ,
99105}
100106
101107impl SysFlags {
102108 fn from_settings ( settings : & PySettings ) -> Self {
103109 // Start with sensible defaults:
104110 let mut flags: SysFlags = Default :: default ( ) ;
105- flags. debug = settings. debug ;
106- flags. inspect = settings. inspect ;
111+ flags. debug = settings. debug as u8 ;
112+ flags. inspect = settings. inspect as u8 ;
107113 flags. optimize = settings. optimize ;
108- flags. no_user_site = settings. no_user_site ;
109- flags. no_site = settings. no_site ;
110- flags. ignore_environment = settings. ignore_environment ;
114+ flags. no_user_site = settings. no_user_site as u8 ;
115+ flags. no_site = settings. no_site as u8 ;
116+ flags. ignore_environment = settings. ignore_environment as u8 ;
111117 flags. verbose = settings. verbose ;
112- flags. quiet = settings. quiet ;
113- flags. dont_write_bytecode = settings. dont_write_bytecode ;
118+ flags. quiet = settings. quiet as u8 ;
119+ flags. dont_write_bytecode = settings. dont_write_bytecode as u8 ;
114120 flags
115121 }
116122}
@@ -173,7 +179,13 @@ fn sys_getrecursionlimit(vm: &VirtualMachine) -> usize {
173179 vm. recursion_limit . get ( )
174180}
175181
176- fn sys_setrecursionlimit ( recursion_limit : usize , vm : & VirtualMachine ) -> PyResult {
182+ fn sys_setrecursionlimit ( recursion_limit : i32 , vm : & VirtualMachine ) -> PyResult {
183+ let recursion_limit = recursion_limit
184+ . to_usize ( )
185+ . filter ( |& u| u >= 1 )
186+ . ok_or_else ( || {
187+ vm. new_value_error ( "recursion limit must be greater than or equal to one" . to_owned ( ) )
188+ } ) ?;
177189 let recursion_depth = vm. frames . borrow ( ) . len ( ) ;
178190
179191 if recursion_limit > recursion_depth + 1 {
@@ -209,7 +221,7 @@ fn sys_git_info(vm: &VirtualMachine) -> PyObjectRef {
209221}
210222
211223fn sys_exit ( code : OptionalArg < PyObjectRef > , vm : & VirtualMachine ) -> PyResult {
212- let code = code. unwrap_or_else ( || vm. new_int ( 0 ) ) ;
224+ let code = code. unwrap_or_else ( || vm. get_none ( ) ) ;
213225 Err ( vm. new_exception ( vm. ctx . exceptions . system_exit . clone ( ) , vec ! [ code] ) )
214226}
215227
@@ -350,7 +362,6 @@ pub fn sysconfigdata_name() -> String {
350362}
351363
352364#[ pystruct_sequence( module = "sys" , name = "hash_info" ) ]
353- #[ derive( Debug ) ]
354365struct PyHashInfo {
355366 width : usize ,
356367 modulus : PyUHash ,
@@ -360,9 +371,10 @@ struct PyHashInfo {
360371 algorithm : & ' static str ,
361372 hash_bits : usize ,
362373 seed_bits : usize ,
374+ cutoff : usize ,
363375}
364376impl PyHashInfo {
365- pub const INFO : Self = {
377+ const INFO : Self = {
366378 use rustpython_common:: hash:: * ;
367379 PyHashInfo {
368380 width : BITS ,
@@ -373,20 +385,73 @@ impl PyHashInfo {
373385 algorithm : ALGO ,
374386 hash_bits : HASH_BITS ,
375387 seed_bits : SEED_BITS ,
388+ cutoff : 0 , // no small string optimizations
376389 }
377390 } ;
378391}
379392
393+ #[ pystruct_sequence( module = "sys" , name = "float_info" ) ]
394+ struct PyFloatInfo {
395+ max : f64 ,
396+ max_exp : i32 ,
397+ max_10_exp : i32 ,
398+ min : f64 ,
399+ min_exp : i32 ,
400+ min_10_exp : i32 ,
401+ dig : u32 ,
402+ mant_dig : u32 ,
403+ epsilon : f64 ,
404+ radix : u32 ,
405+ rounds : i32 ,
406+ }
407+ impl PyFloatInfo {
408+ const INFO : Self = PyFloatInfo {
409+ max : f64:: MAX ,
410+ max_exp : f64:: MAX_EXP ,
411+ max_10_exp : f64:: MAX_10_EXP ,
412+ min : f64:: MIN ,
413+ min_exp : f64:: MIN_EXP ,
414+ min_10_exp : f64:: MIN_10_EXP ,
415+ dig : f64:: DIGITS ,
416+ mant_dig : f64:: MANTISSA_DIGITS ,
417+ epsilon : f64:: EPSILON ,
418+ radix : f64:: RADIX ,
419+ rounds : 1 , // FE_TONEAREST
420+ } ;
421+ }
422+
423+ #[ pystruct_sequence( module = "sys" , name = "int_info" ) ]
424+ struct PyIntInfo {
425+ bits_per_digit : usize ,
426+ sizeof_digit : usize ,
427+ }
428+ impl PyIntInfo {
429+ const INFO : Self = PyIntInfo {
430+ bits_per_digit : 30 , //?
431+ sizeof_digit : std:: mem:: size_of :: < u32 > ( ) ,
432+ } ;
433+ }
434+
380435pub fn make_module ( vm : & VirtualMachine , module : PyObjectRef , builtins : PyObjectRef ) {
381436 let ctx = & vm. ctx ;
382437
383438 let flags_type = SysFlags :: make_class ( ctx) ;
439+ extend_class ! ( ctx, flags_type, {
440+ ( slot new) => |_cls: PyClassRef , _args: PyFuncArgs , vm: & VirtualMachine | -> PyResult {
441+ Err ( vm. new_type_error( "cannot create 'sys.flags' instances" . to_owned( ) ) )
442+ } ,
443+ } ) ;
384444 let flags = SysFlags :: from_settings ( & vm. state . settings )
385445 . into_struct_sequence ( vm, flags_type)
386446 . unwrap ( ) ;
387447
388448 let version_info_type = version:: VersionInfo :: make_class ( ctx) ;
389- let version_info = version:: get_version_info ( )
449+ extend_class ! ( ctx, version_info_type, {
450+ ( slot new) => |_cls: PyClassRef , _args: PyFuncArgs , vm: & VirtualMachine | -> PyResult {
451+ Err ( vm. new_type_error( "cannot create 'sys.version_info' instances" . to_owned( ) ) )
452+ } ,
453+ } ) ;
454+ let version_info = version:: VersionInfo :: VERSION
390455 . into_struct_sequence ( vm, version_info_type)
391456 . unwrap ( ) ;
392457
@@ -395,11 +460,23 @@ pub fn make_module(vm: &VirtualMachine, module: PyObjectRef, builtins: PyObjectR
395460 . into_struct_sequence ( vm, hash_info_type)
396461 . unwrap ( ) ;
397462
463+ let float_info_type = PyFloatInfo :: make_class ( ctx) ;
464+ let float_info = PyFloatInfo :: INFO
465+ . into_struct_sequence ( vm, float_info_type)
466+ . unwrap ( ) ;
467+
468+ let int_info_type = PyIntInfo :: make_class ( ctx) ;
469+ let int_info = PyIntInfo :: INFO
470+ . into_struct_sequence ( vm, int_info_type)
471+ . unwrap ( ) ;
472+
398473 // TODO Add crate version to this namespace
399474 let implementation = py_namespace ! ( vm, {
400475 "name" => ctx. new_str( "rustpython" . to_owned( ) ) ,
401476 "cache_tag" => ctx. new_str( "rustpython-01" . to_owned( ) ) ,
402477 "_multiarch" => ctx. new_str( MULTIARCH . to_owned( ) ) ,
478+ "version" => version_info. clone( ) ,
479+ "hexversion" => ctx. new_int( version:: VERSION_HEX ) ,
403480 } ) ;
404481
405482 let path = ctx. new_list (
@@ -532,7 +609,7 @@ settrace() -- set the global debug tracing function
532609 "gettrace" => ctx. new_function( sys_gettrace) ,
533610 "hash_info" => hash_info,
534611 "intern" => ctx. new_function( sys_intern) ,
535- "maxunicode" => ctx. new_int( 0x0010_FFFF ) ,
612+ "maxunicode" => ctx. new_int( std :: char :: MAX as u32 ) ,
536613 "maxsize" => ctx. new_int( std:: isize :: MAX ) ,
537614 "path" => path,
538615 "ps1" => ctx. new_str( ">>>>> " . to_owned( ) ) ,
@@ -566,6 +643,11 @@ settrace() -- set the global debug tracing function
566643 "__displayhook__" => ctx. new_function( sys_displayhook) ,
567644 "excepthook" => ctx. new_function( sys_excepthook) ,
568645 "__excepthook__" => ctx. new_function( sys_excepthook) ,
646+ "hexversion" => ctx. new_int( version:: VERSION_HEX ) ,
647+ "api_version" => ctx. new_int( 0x0 ) , // what C api?
648+ "float_info" => float_info,
649+ "int_info" => int_info,
650+ "float_repr_style" => ctx. new_str( "short" . to_owned( ) ) ,
569651 } ) ;
570652
571653 #[ cfg( windows) ]
0 commit comments