@@ -24,8 +24,8 @@ mod builtins {
2424 format:: call_object_format,
2525 function:: Either ,
2626 function:: {
27- ArgBytesLike , ArgCallable , ArgIntoBool , ArgIterable , ArgMapping , FuncArgs , KwArgs ,
28- OptionalArg , OptionalOption , PosArgs , PyArithmeticValue ,
27+ ArgBytesLike , ArgCallable , ArgIntoBool , ArgIterable , ArgMapping , ArgStrOrBytesLike ,
28+ FuncArgs , KwArgs , OptionalArg , OptionalOption , PosArgs , PyArithmeticValue ,
2929 } ,
3030 protocol:: { PyIter , PyIterReturn } ,
3131 py_io,
@@ -248,11 +248,34 @@ mod builtins {
248248 #[ cfg( feature = "rustpython-compiler" ) ]
249249 #[ pyfunction]
250250 fn eval (
251- source : Either < PyStrRef , PyRef < crate :: builtins:: PyCode > > ,
251+ source : Either < ArgStrOrBytesLike , PyRef < crate :: builtins:: PyCode > > ,
252252 scope : ScopeArgs ,
253253 vm : & VirtualMachine ,
254254 ) -> PyResult {
255- run_code ( vm, source, scope, compile:: Mode :: Eval , "eval" )
255+ // source as string
256+ let code = match source {
257+ Either :: A ( either) => {
258+ let source: & [ u8 ] = & either. borrow_bytes ( ) ;
259+ if source. contains ( & 0 ) {
260+ return Err ( vm. new_value_error (
261+ "source code string cannot contain null bytes" . to_owned ( ) ,
262+ ) ) ;
263+ }
264+
265+ let source = std:: str:: from_utf8 ( source) . map_err ( |err| {
266+ let msg = format ! (
267+ "(unicode error) 'utf-8' codec can't decode byte 0x{:x?} in position {}: invalid start byte" ,
268+ source[ err. valid_up_to( ) ] ,
269+ err. valid_up_to( )
270+ ) ;
271+
272+ vm. new_exception_msg ( vm. ctx . exceptions . syntax_error . to_owned ( ) , msg)
273+ } ) ?;
274+ Ok ( Either :: A ( vm. ctx . new_str ( source) ) )
275+ }
276+ Either :: B ( code) => Ok ( Either :: B ( code) ) ,
277+ } ?;
278+ run_code ( vm, code, scope, compile:: Mode :: Eval , "eval" )
256279 }
257280
258281 /// Implements `exec`
0 commit comments