@@ -12,7 +12,7 @@ use pyo3::types::{
1212use pyo3:: types:: { PyDictItems , PyDictKeys , PyDictValues } ;
1313use pyo3:: { ffi, intern, AsPyPointer , PyTypeInfo } ;
1414
15- use crate :: errors:: { py_err_string, ErrorKind , InputValue , LocItem , ValError , ValResult } ;
15+ use crate :: errors:: { py_err_string, ErrorKind , InputValue , LocItem , ValError , ValLineError , ValResult } ;
1616
1717use super :: datetime:: {
1818 bytes_as_date, bytes_as_datetime, bytes_as_time, bytes_as_timedelta, date_as_datetime, float_as_datetime,
@@ -114,26 +114,54 @@ impl<'a> Input<'a> for PyAny {
114114 }
115115
116116 fn validate_args ( & ' a self ) -> ValResult < ' a , GenericArguments < ' a > > {
117- if let Ok ( kwargs) = self . cast_as :: < PyDict > ( ) {
118- Ok ( PyArgs :: new ( None , Some ( kwargs) ) . into ( ) )
119- } else if let Ok ( ( args, kwargs) ) = self . extract :: < ( & PyAny , & PyAny ) > ( ) {
120- let args = if let Ok ( tuple) = args. cast_as :: < PyTuple > ( ) {
121- Some ( tuple)
122- } else if args. is_none ( ) {
123- None
124- } else if let Ok ( list) = args. cast_as :: < PyList > ( ) {
125- Some ( PyTuple :: new ( self . py ( ) , list. iter ( ) . collect :: < Vec < _ > > ( ) ) )
126- } else {
127- return Err ( ValError :: new ( ErrorKind :: ArgumentsType , self ) ) ;
128- } ;
129- let kwargs = if let Ok ( dict) = kwargs. cast_as :: < PyDict > ( ) {
130- Some ( dict)
131- } else if kwargs. is_none ( ) {
132- None
133- } else {
134- return Err ( ValError :: new ( ErrorKind :: ArgumentsType , self ) ) ;
135- } ;
136- Ok ( PyArgs :: new ( args, kwargs) . into ( ) )
117+ if let Ok ( dict) = self . cast_as :: < PyDict > ( ) {
118+ if let Some ( args) = dict. get_item ( "__args__" ) {
119+ if let Some ( kwargs) = dict. get_item ( "__kwargs__" ) {
120+ // we only try this logic if there are only these two items in the dict
121+ if dict. len ( ) == 2 {
122+ let args = if let Ok ( tuple) = args. cast_as :: < PyTuple > ( ) {
123+ Ok ( Some ( tuple) )
124+ } else if args. is_none ( ) {
125+ Ok ( None )
126+ } else if let Ok ( list) = args. cast_as :: < PyList > ( ) {
127+ Ok ( Some ( PyTuple :: new ( self . py ( ) , list. iter ( ) . collect :: < Vec < _ > > ( ) ) ) )
128+ } else {
129+ Err ( ValLineError :: new_with_loc (
130+ ErrorKind :: PositionalArgumentsType ,
131+ args,
132+ "__args__" ,
133+ ) )
134+ } ;
135+
136+ let kwargs = if let Ok ( dict) = kwargs. cast_as :: < PyDict > ( ) {
137+ Ok ( Some ( dict) )
138+ } else if kwargs. is_none ( ) {
139+ Ok ( None )
140+ } else {
141+ Err ( ValLineError :: new_with_loc (
142+ ErrorKind :: KeywordArgumentsType ,
143+ kwargs,
144+ "__kwargs__" ,
145+ ) )
146+ } ;
147+
148+ return match ( args, kwargs) {
149+ ( Ok ( args) , Ok ( kwargs) ) => Ok ( PyArgs :: new ( args, kwargs) . into ( ) ) ,
150+ ( Err ( args_error) , Err ( kwargs_error) ) => {
151+ Err ( ValError :: LineErrors ( vec ! [ args_error, kwargs_error] ) )
152+ }
153+ ( Err ( error) , _) => Err ( ValError :: LineErrors ( vec ! [ error] ) ) ,
154+ ( _, Err ( error) ) => Err ( ValError :: LineErrors ( vec ! [ error] ) ) ,
155+ } ;
156+ }
157+ }
158+ }
159+ Ok ( PyArgs :: new ( None , Some ( dict) ) . into ( ) )
160+ } else if let Ok ( tuple) = self . cast_as :: < PyTuple > ( ) {
161+ Ok ( PyArgs :: new ( Some ( tuple) , None ) . into ( ) )
162+ } else if let Ok ( list) = self . cast_as :: < PyList > ( ) {
163+ let tuple = PyTuple :: new ( self . py ( ) , list. iter ( ) . collect :: < Vec < _ > > ( ) ) ;
164+ Ok ( PyArgs :: new ( Some ( tuple) , None ) . into ( ) )
137165 } else {
138166 Err ( ValError :: new ( ErrorKind :: ArgumentsType , self ) )
139167 }
0 commit comments