1
1
use crate :: model:: {
2
- Argument , Arguments , Attribute , Class , Function , Module , VariableLengthArgument ,
2
+ Argument , Arguments , Attribute , Class , Function , Module , TypeHint , TypeHintImport ,
3
+ VariableLengthArgument ,
3
4
} ;
4
5
use anyhow:: { bail, ensure, Context , Result } ;
5
6
use goblin:: elf:: Elf ;
@@ -8,11 +9,12 @@ use goblin::mach::symbols::{NO_SECT, N_SECT};
8
9
use goblin:: mach:: { Mach , MachO , SingleArch } ;
9
10
use goblin:: pe:: PE ;
10
11
use goblin:: Object ;
11
- use serde:: Deserialize ;
12
+ use serde:: de:: { Error , MapAccess , Visitor } ;
13
+ use serde:: { de, Deserialize , Deserializer } ;
12
14
use std:: cmp:: Ordering ;
13
15
use std:: collections:: HashMap ;
14
- use std:: fs;
15
16
use std:: path:: Path ;
17
+ use std:: { fmt, fs} ;
16
18
17
19
/// Introspect a cdylib built with PyO3 and returns the definition of a Python module.
18
20
///
@@ -191,7 +193,7 @@ fn convert_function(
191
193
name : & str ,
192
194
arguments : & ChunkArguments ,
193
195
decorators : & [ String ] ,
194
- returns : & Option < String > ,
196
+ returns : & Option < ChunkTypeHint > ,
195
197
) -> Function {
196
198
Function {
197
199
name : name. into ( ) ,
@@ -209,30 +211,48 @@ fn convert_function(
209
211
. as_ref ( )
210
212
. map ( convert_variable_length_argument) ,
211
213
} ,
212
- returns : returns. clone ( ) ,
214
+ returns : returns. as_ref ( ) . map ( convert_type_hint ) ,
213
215
}
214
216
}
215
217
216
218
fn convert_argument ( arg : & ChunkArgument ) -> Argument {
217
219
Argument {
218
220
name : arg. name . clone ( ) ,
219
221
default_value : arg. default . clone ( ) ,
220
- annotation : arg. annotation . clone ( ) ,
222
+ annotation : arg. annotation . as_ref ( ) . map ( convert_type_hint ) ,
221
223
}
222
224
}
223
225
224
226
fn convert_variable_length_argument ( arg : & ChunkArgument ) -> VariableLengthArgument {
225
227
VariableLengthArgument {
226
228
name : arg. name . clone ( ) ,
227
- annotation : arg. annotation . clone ( ) ,
229
+ annotation : arg. annotation . as_ref ( ) . map ( convert_type_hint ) ,
228
230
}
229
231
}
230
232
231
- fn convert_attribute ( name : & str , value : & Option < String > , annotation : & Option < String > ) -> Attribute {
233
+ fn convert_attribute (
234
+ name : & str ,
235
+ value : & Option < String > ,
236
+ annotation : & Option < ChunkTypeHint > ,
237
+ ) -> Attribute {
232
238
Attribute {
233
239
name : name. into ( ) ,
234
240
value : value. clone ( ) ,
235
- annotation : annotation. clone ( ) ,
241
+ annotation : annotation. as_ref ( ) . map ( convert_type_hint) ,
242
+ }
243
+ }
244
+
245
+ fn convert_type_hint ( arg : & ChunkTypeHint ) -> TypeHint {
246
+ TypeHint {
247
+ annotation : arg. annotation . clone ( ) ,
248
+ imports : arg. imports . iter ( ) . map ( convert_type_hint_import) . collect ( ) ,
249
+ }
250
+ }
251
+
252
+ fn convert_type_hint_import ( arg : & ChunkTypeHintImport ) -> TypeHintImport {
253
+ TypeHintImport {
254
+ module : arg. module . clone ( ) ,
255
+ name : arg. name . clone ( ) ,
236
256
}
237
257
}
238
258
@@ -414,8 +434,8 @@ enum Chunk {
414
434
parent : Option < String > ,
415
435
#[ serde( default ) ]
416
436
decorators : Vec < String > ,
417
- #[ serde( default ) ]
418
- returns : Option < String > ,
437
+ #[ serde( default , deserialize_with = "deserialize_annotation" ) ]
438
+ returns : Option < ChunkTypeHint > ,
419
439
} ,
420
440
Attribute {
421
441
#[ serde( default ) ]
@@ -425,8 +445,8 @@ enum Chunk {
425
445
name : String ,
426
446
#[ serde( default ) ]
427
447
value : Option < String > ,
428
- #[ serde( default ) ]
429
- annotation : Option < String > ,
448
+ #[ serde( default , deserialize_with = "deserialize_annotation" ) ]
449
+ annotation : Option < ChunkTypeHint > ,
430
450
} ,
431
451
}
432
452
@@ -449,6 +469,56 @@ struct ChunkArgument {
449
469
name : String ,
450
470
#[ serde( default ) ]
451
471
default : Option < String > ,
472
+ #[ serde( default , deserialize_with = "deserialize_annotation" ) ]
473
+ annotation : Option < ChunkTypeHint > ,
474
+ }
475
+
476
+ #[ derive( Deserialize ) ]
477
+ struct ChunkTypeHint {
478
+ annotation : String ,
452
479
#[ serde( default ) ]
453
- annotation : Option < String > ,
480
+ imports : Vec < ChunkTypeHintImport > ,
481
+ }
482
+
483
+ #[ derive( Deserialize ) ]
484
+ struct ChunkTypeHintImport {
485
+ module : String ,
486
+ name : String ,
487
+ }
488
+
489
+ fn deserialize_annotation < ' de , D : Deserializer < ' de > > (
490
+ deserializer : D ,
491
+ ) -> Result < Option < ChunkTypeHint > , D :: Error > {
492
+ struct AnnotationVisitor ;
493
+
494
+ impl < ' de > Visitor < ' de > for AnnotationVisitor {
495
+ type Value = ChunkTypeHint ;
496
+
497
+ fn expecting ( & self , formatter : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
498
+ formatter. write_str ( "annotation" )
499
+ }
500
+
501
+ fn visit_str < E > ( self , v : & str ) -> Result < Self :: Value , E >
502
+ where
503
+ E : Error ,
504
+ {
505
+ self . visit_string ( v. into ( ) )
506
+ }
507
+
508
+ fn visit_string < E > ( self , v : String ) -> Result < Self :: Value , E >
509
+ where
510
+ E : Error ,
511
+ {
512
+ Ok ( ChunkTypeHint {
513
+ annotation : v,
514
+ imports : Vec :: new ( ) ,
515
+ } )
516
+ }
517
+
518
+ fn visit_map < M : MapAccess < ' de > > ( self , map : M ) -> Result < ChunkTypeHint , M :: Error > {
519
+ Deserialize :: deserialize ( de:: value:: MapAccessDeserializer :: new ( map) )
520
+ }
521
+ }
522
+
523
+ Ok ( Some ( deserializer. deserialize_any ( AnnotationVisitor ) ?) )
454
524
}
0 commit comments