@@ -12,7 +12,7 @@ use pyo3::types::{
12
12
use pyo3:: types:: { PyDictItems , PyDictKeys , PyDictValues } ;
13
13
use pyo3:: { ffi, intern, AsPyPointer , PyTypeInfo } ;
14
14
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 } ;
16
16
17
17
use super :: datetime:: {
18
18
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 {
114
114
}
115
115
116
116
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 ( ) )
137
165
} else {
138
166
Err ( ValError :: new ( ErrorKind :: ArgumentsType , self ) )
139
167
}
0 commit comments