1use depyler_hir::hir::{Import, ImportItem};
4use std::collections::HashMap;
5
6#[cfg(test)]
7#[path = "module_mapper_tests.rs"]
8mod tests;
9
10pub struct ModuleMapper {
12 module_map: HashMap<String, ModuleMapping>,
14}
15
16#[derive(Debug, Clone, PartialEq)]
18pub enum ConstructorPattern {
19 New,
21 Function,
23 Method(String),
25}
26
27#[derive(Debug, Clone)]
28pub struct ModuleMapping {
29 pub rust_path: String,
31 pub is_external: bool,
33 pub version: Option<String>,
35 pub item_map: HashMap<String, String>,
37 pub constructor_patterns: HashMap<String, ConstructorPattern>,
40}
41
42impl ModuleMapper {
43 pub fn new() -> Self {
55 let mut module_map = HashMap::new();
56
57 module_map.insert(
59 "os".to_string(),
60 ModuleMapping {
61 rust_path: "std".to_string(),
62 is_external: false,
63 version: None,
64 item_map: HashMap::from([
65 ("getcwd".to_string(), "env::current_dir".to_string()),
66 ("environ".to_string(), "env::vars".to_string()),
67 ("path".to_string(), "path::Path".to_string()),
68 ("getenv".to_string(), "env::var".to_string()),
69 ]),
70 constructor_patterns: HashMap::new(),
71 },
72 );
73
74 module_map.insert(
75 "os.path".to_string(),
76 ModuleMapping {
77 rust_path: "std::path".to_string(),
78 is_external: false,
79 version: None,
80 item_map: HashMap::from([
81 ("join".to_string(), "Path::join".to_string()),
82 ("exists".to_string(), "Path::exists".to_string()),
83 ("basename".to_string(), "Path::file_name".to_string()),
84 ("dirname".to_string(), "Path::parent".to_string()),
85 ("splitext".to_string(), "Path".to_string()),
88 ("split".to_string(), "Path".to_string()),
89 ("normpath".to_string(), "Path".to_string()),
90 ("isfile".to_string(), "Path::is_file".to_string()),
91 ("isdir".to_string(), "Path::is_dir".to_string()),
92 ("isabs".to_string(), "Path::is_absolute".to_string()),
93 ("abspath".to_string(), "Path::canonicalize".to_string()),
94 ]),
95 constructor_patterns: HashMap::new(),
96 },
97 );
98
99 module_map.insert(
100 "sys".to_string(),
101 ModuleMapping {
102 rust_path: "std".to_string(),
103 is_external: false,
104 version: None,
105 item_map: HashMap::from([
106 ("argv".to_string(), "env::args".to_string()),
107 ("exit".to_string(), "process::exit".to_string()),
108 ("stdin".to_string(), "io::stdin".to_string()),
109 ("stdout".to_string(), "io::stdout".to_string()),
110 ("stderr".to_string(), "io::stderr".to_string()),
111 ]),
112 constructor_patterns: HashMap::new(),
113 },
114 );
115
116 module_map.insert(
118 "io".to_string(),
119 ModuleMapping {
120 rust_path: "std::io".to_string(),
121 is_external: false,
122 version: None,
123 item_map: HashMap::from([
124 ("BufferedReader".to_string(), "BufReader".to_string()),
125 ("BufferedWriter".to_string(), "BufWriter".to_string()),
126 ("BytesIO".to_string(), "Cursor".to_string()),
127 ("StringIO".to_string(), "Cursor".to_string()),
128 ]),
129 constructor_patterns: HashMap::from([
131 ("BufReader".to_string(), ConstructorPattern::New),
133 ("BufWriter".to_string(), ConstructorPattern::New),
134 ("Cursor".to_string(), ConstructorPattern::New),
136 ]),
137 },
138 );
139
140 module_map.insert(
141 "json".to_string(),
142 ModuleMapping {
143 rust_path: "serde_json".to_string(),
144 is_external: true,
145 version: Some("1.0".to_string()),
146 item_map: HashMap::from([
147 ("loads".to_string(), "from_str".to_string()),
148 ("dumps".to_string(), "to_string".to_string()),
149 ("load".to_string(), "from_reader".to_string()),
150 ("dump".to_string(), "to_writer".to_string()),
151 ]),
152 constructor_patterns: HashMap::new(),
153 },
154 );
155
156 module_map.insert(
158 "re".to_string(),
159 ModuleMapping {
160 rust_path: "regex".to_string(),
161 is_external: true,
162 version: Some("1.10".to_string()),
163 item_map: HashMap::from([
164 ("compile".to_string(), "Regex::new".to_string()),
166 ("search".to_string(), "Regex::find".to_string()),
167 ("match".to_string(), "Regex::is_match".to_string()),
168 ("findall".to_string(), "Regex::find_iter".to_string()),
169 ("finditer".to_string(), "Regex::find_iter".to_string()),
170 ("Pattern".to_string(), "Regex".to_string()),
171 ("sub".to_string(), "Regex::replace_all".to_string()),
173 ("subn".to_string(), "Regex::replace_all".to_string()),
174 ("split".to_string(), "Regex::split".to_string()),
176 ("IGNORECASE".to_string(), "(?i)".to_string()),
178 ("I".to_string(), "(?i)".to_string()),
179 ("MULTILINE".to_string(), "(?m)".to_string()),
180 ("M".to_string(), "(?m)".to_string()),
181 ("DOTALL".to_string(), "(?s)".to_string()),
182 ("S".to_string(), "(?s)".to_string()),
183 ("VERBOSE".to_string(), "(?x)".to_string()),
184 ("X".to_string(), "(?x)".to_string()),
185 ]),
186 constructor_patterns: HashMap::from([(
188 "Regex".to_string(),
189 ConstructorPattern::Method("new".to_string()),
190 )]),
191 },
192 );
193
194 module_map.insert(
195 "datetime".to_string(),
196 ModuleMapping {
197 rust_path: "chrono".to_string(),
198 is_external: true,
199 version: Some("0.4".to_string()),
200 item_map: HashMap::from([
201 ("datetime".to_string(), "DateTime".to_string()),
202 ("date".to_string(), "NaiveDate".to_string()),
203 ("time".to_string(), "NaiveTime".to_string()),
204 ("timedelta".to_string(), "Duration".to_string()),
205 ]),
206 constructor_patterns: HashMap::from([
208 (
209 "DateTime".to_string(),
210 ConstructorPattern::Method("now".to_string()),
211 ),
212 (
213 "NaiveDate".to_string(),
214 ConstructorPattern::Method("from_ymd_opt".to_string()),
215 ),
216 (
217 "NaiveTime".to_string(),
218 ConstructorPattern::Method("from_hms_opt".to_string()),
219 ),
220 (
221 "Duration".to_string(),
222 ConstructorPattern::Method("seconds".to_string()),
223 ),
224 ]),
225 },
226 );
227
228 module_map.insert(
229 "typing".to_string(),
230 ModuleMapping {
231 rust_path: "".to_string(), is_external: false,
233 version: None,
234 item_map: HashMap::from([
235 ("List".to_string(), "Vec".to_string()),
236 ("Dict".to_string(), "HashMap".to_string()),
237 ("Set".to_string(), "HashSet".to_string()),
238 ("Tuple".to_string(), "".to_string()), ("Optional".to_string(), "Option".to_string()),
240 ("Union".to_string(), "".to_string()), ("Any".to_string(), "".to_string()), ]),
243 constructor_patterns: HashMap::new(),
244 },
245 );
246
247 module_map.insert(
248 "collections".to_string(),
249 ModuleMapping {
250 rust_path: "std::collections".to_string(),
251 is_external: false,
252 version: None,
253 item_map: HashMap::from([
254 ("defaultdict".to_string(), "HashMap".to_string()),
257 ("Counter".to_string(), "HashMap".to_string()),
258 ("deque".to_string(), "VecDeque".to_string()),
259 ("OrderedDict".to_string(), "HashMap".to_string()),
262 ]),
263 constructor_patterns: HashMap::from([
265 ("defaultdict".to_string(), ConstructorPattern::New),
266 ("Counter".to_string(), ConstructorPattern::New),
267 ("deque".to_string(), ConstructorPattern::New),
268 ("OrderedDict".to_string(), ConstructorPattern::New),
269 ("VecDeque".to_string(), ConstructorPattern::New),
270 ("HashMap".to_string(), ConstructorPattern::New),
271 ("HashSet".to_string(), ConstructorPattern::New),
272 ("BTreeMap".to_string(), ConstructorPattern::New),
273 ("BTreeSet".to_string(), ConstructorPattern::New),
274 ]),
275 },
276 );
277
278 module_map.insert(
279 "math".to_string(),
280 ModuleMapping {
281 rust_path: "std::f64".to_string(),
282 is_external: false,
283 version: None,
284 item_map: HashMap::from([
285 ("sqrt".to_string(), "sqrt".to_string()),
286 ("sin".to_string(), "sin".to_string()),
287 ("cos".to_string(), "cos".to_string()),
288 ("tan".to_string(), "tan".to_string()),
289 ("pi".to_string(), "consts::PI".to_string()),
290 ("e".to_string(), "consts::E".to_string()),
291 ("isqrt".to_string(), "isqrt".to_string()),
293 ]),
294 constructor_patterns: HashMap::new(),
295 },
296 );
297
298 module_map.insert(
300 "random".to_string(),
301 ModuleMapping {
302 rust_path: "rand".to_string(),
303 is_external: true,
304 version: Some("0.8".to_string()),
305 item_map: HashMap::from([
306 ("random".to_string(), "random".to_string()),
307 ("randint".to_string(), "gen_range".to_string()),
308 ("choice".to_string(), "choose".to_string()),
309 ("shuffle".to_string(), "shuffle".to_string()),
310 ("uniform".to_string(), "gen_range".to_string()),
312 ("seed".to_string(), "SeedableRng::seed_from_u64".to_string()),
313 ("randrange".to_string(), "gen_range".to_string()),
314 ("sample".to_string(), "choose_multiple".to_string()),
315 ("gauss".to_string(), "Normal::sample".to_string()),
316 ]),
317 constructor_patterns: HashMap::new(),
318 },
319 );
320
321 module_map.insert(
322 "itertools".to_string(),
323 ModuleMapping {
324 rust_path: "itertools".to_string(),
325 is_external: true,
326 version: Some("0.11".to_string()),
327 item_map: HashMap::from([
328 ("chain".to_string(), "chain".to_string()),
329 ("combinations".to_string(), "combinations".to_string()),
330 ("permutations".to_string(), "permutations".to_string()),
331 ("product".to_string(), "iproduct".to_string()),
332 ("groupby".to_string(), "Itertools".to_string()),
334 ("accumulate".to_string(), "scan".to_string()),
335 ("takewhile".to_string(), "take_while".to_string()),
336 ("dropwhile".to_string(), "drop_while".to_string()),
337 ("cycle".to_string(), "cycle".to_string()),
338 ("repeat".to_string(), "repeat_n".to_string()),
339 ]),
340 constructor_patterns: HashMap::new(),
341 },
342 );
343
344 module_map.insert(
345 "functools".to_string(),
346 ModuleMapping {
347 rust_path: "std".to_string(),
348 is_external: false,
349 version: None,
350 item_map: HashMap::from([
351 ("reduce".to_string(), "".to_string()), ("partial".to_string(), "".to_string()), ("lru_cache".to_string(), "".to_string()), ("wraps".to_string(), "".to_string()), ]),
356 constructor_patterns: HashMap::new(),
357 },
358 );
359
360 module_map.insert(
361 "hashlib".to_string(),
362 ModuleMapping {
363 rust_path: "sha2".to_string(),
364 is_external: true,
365 version: Some("0.10".to_string()),
366 item_map: HashMap::from([
367 ("sha256".to_string(), "Sha256".to_string()),
368 ("sha512".to_string(), "Sha512".to_string()),
369 ("sha1".to_string(), "Sha1".to_string()),
370 ("md5".to_string(), "Md5".to_string()),
371 ]),
372 constructor_patterns: HashMap::new(),
373 },
374 );
375
376 module_map.insert(
377 "base64".to_string(),
378 ModuleMapping {
379 rust_path: "base64".to_string(),
380 is_external: true,
381 version: Some("0.21".to_string()),
382 item_map: HashMap::from([
383 ("b64encode".to_string(), "encode".to_string()),
384 ("b64decode".to_string(), "decode".to_string()),
385 ("urlsafe_b64encode".to_string(), "encode_config".to_string()),
386 ("urlsafe_b64decode".to_string(), "decode_config".to_string()),
387 ]),
388 constructor_patterns: HashMap::new(),
389 },
390 );
391
392 module_map.insert(
393 "urllib.parse".to_string(),
394 ModuleMapping {
395 rust_path: "url".to_string(),
396 is_external: true,
397 version: Some("2.5".to_string()),
398 item_map: HashMap::from([
399 ("urlparse".to_string(), "Url::parse".to_string()),
400 ("urljoin".to_string(), "Url::join".to_string()),
401 (
402 "quote".to_string(),
403 "percent_encoding::percent_encode".to_string(),
404 ),
405 (
406 "unquote".to_string(),
407 "percent_encoding::percent_decode".to_string(),
408 ),
409 ]),
410 constructor_patterns: HashMap::new(),
411 },
412 );
413
414 module_map.insert(
415 "pathlib".to_string(),
416 ModuleMapping {
417 rust_path: "std::path".to_string(),
418 is_external: false,
419 version: None,
420 item_map: HashMap::from([
421 ("Path".to_string(), "PathBuf".to_string()),
422 ("PurePath".to_string(), "Path".to_string()),
423 ]),
424 constructor_patterns: HashMap::from([
426 (
427 "PathBuf".to_string(),
428 ConstructorPattern::Method("from".to_string()),
429 ),
430 (
431 "Path".to_string(),
432 ConstructorPattern::Method("new".to_string()),
433 ),
434 ]),
435 },
436 );
437
438 module_map.insert(
439 "tempfile".to_string(),
440 ModuleMapping {
441 rust_path: "tempfile".to_string(),
442 is_external: true,
443 version: Some("3.0".to_string()),
444 item_map: HashMap::from([
445 (
446 "NamedTemporaryFile".to_string(),
447 "NamedTempFile".to_string(),
448 ),
449 ("TemporaryDirectory".to_string(), "TempDir".to_string()),
450 ("mkstemp".to_string(), "tempfile".to_string()),
451 ("mkdtemp".to_string(), "tempdir".to_string()),
452 ]),
453 constructor_patterns: HashMap::from([
455 ("NamedTempFile".to_string(), ConstructorPattern::New),
457 ("TempDir".to_string(), ConstructorPattern::New),
459 ("tempfile".to_string(), ConstructorPattern::Function),
461 ("tempdir".to_string(), ConstructorPattern::Function),
463 ]),
464 },
465 );
466
467 module_map.insert(
468 "csv".to_string(),
469 ModuleMapping {
470 rust_path: "csv".to_string(),
471 is_external: true,
472 version: Some("1.0".to_string()),
473 item_map: HashMap::from([
474 ("reader".to_string(), "Reader".to_string()),
475 ("writer".to_string(), "Writer".to_string()),
476 ("DictReader".to_string(), "Reader".to_string()),
477 ("DictWriter".to_string(), "Writer".to_string()),
478 ]),
479 constructor_patterns: HashMap::new(),
480 },
481 );
482
483 module_map.insert(
490 "numpy".to_string(),
491 ModuleMapping {
492 rust_path: "trueno".to_string(),
493 is_external: true,
494 version: Some("0.7".to_string()),
495 item_map: HashMap::from([
496 ("array".to_string(), "Vector::from_slice".to_string()),
498 ("zeros".to_string(), "Vector::zeros".to_string()),
499 ("ones".to_string(), "Vector::ones".to_string()),
500 ("empty".to_string(), "Vector::zeros".to_string()),
501 ("arange".to_string(), "Vector::arange".to_string()),
502 ("linspace".to_string(), "Vector::linspace".to_string()),
503 ("add".to_string(), "Vector::add".to_string()),
505 ("subtract".to_string(), "Vector::sub".to_string()),
506 ("multiply".to_string(), "Vector::mul".to_string()),
507 ("divide".to_string(), "Vector::div".to_string()),
508 ("sqrt".to_string(), "Vector::sqrt".to_string()),
509 ("exp".to_string(), "Vector::exp".to_string()),
510 ("log".to_string(), "Vector::ln".to_string()),
511 ("sin".to_string(), "Vector::sin".to_string()),
512 ("cos".to_string(), "Vector::cos".to_string()),
513 ("abs".to_string(), "Vector::abs".to_string()),
514 ("dot".to_string(), "Vector::dot".to_string()),
516 ("matmul".to_string(), "Matrix::matmul".to_string()),
517 ("sum".to_string(), "Vector::sum".to_string()),
519 ("mean".to_string(), "Vector::mean".to_string()),
520 ("max".to_string(), "Vector::max".to_string()),
521 ("min".to_string(), "Vector::min".to_string()),
522 ("std".to_string(), "Vector::std".to_string()),
523 ("var".to_string(), "Vector::var".to_string()),
524 ("argmax".to_string(), "Vector::argmax".to_string()),
525 ("argmin".to_string(), "Vector::argmin".to_string()),
526 ("reshape".to_string(), "Matrix::reshape".to_string()),
528 ("transpose".to_string(), "Matrix::transpose".to_string()),
529 ("flatten".to_string(), "Vector::flatten".to_string()),
530 ]),
531 constructor_patterns: HashMap::new(),
532 },
533 );
534
535 module_map.insert(
537 "numpy.linalg".to_string(),
538 ModuleMapping {
539 rust_path: "trueno::linalg".to_string(),
540 is_external: true,
541 version: Some("0.7".to_string()),
542 item_map: HashMap::from([
543 ("norm".to_string(), "norm".to_string()),
544 ("inv".to_string(), "inv".to_string()),
545 ("det".to_string(), "det".to_string()),
546 ("eig".to_string(), "eig".to_string()),
547 ("svd".to_string(), "svd".to_string()),
548 ("solve".to_string(), "solve".to_string()),
549 ]),
550 constructor_patterns: HashMap::new(),
551 },
552 );
553
554 module_map.insert(
559 "sklearn.linear_model".to_string(),
560 ModuleMapping {
561 rust_path: "aprender::linear".to_string(),
562 is_external: true,
563 version: Some("0.14".to_string()),
564 item_map: HashMap::from([
565 (
566 "LinearRegression".to_string(),
567 "LinearRegression".to_string(),
568 ),
569 (
570 "LogisticRegression".to_string(),
571 "LogisticRegression".to_string(),
572 ),
573 ("Ridge".to_string(), "Ridge".to_string()),
574 ("Lasso".to_string(), "Lasso".to_string()),
575 ("ElasticNet".to_string(), "ElasticNet".to_string()),
576 ]),
577 constructor_patterns: HashMap::from([
578 ("LinearRegression".to_string(), ConstructorPattern::New),
579 ("LogisticRegression".to_string(), ConstructorPattern::New),
580 ]),
581 },
582 );
583
584 module_map.insert(
586 "sklearn.cluster".to_string(),
587 ModuleMapping {
588 rust_path: "aprender::cluster".to_string(),
589 is_external: true,
590 version: Some("0.14".to_string()),
591 item_map: HashMap::from([
592 ("KMeans".to_string(), "KMeans".to_string()),
593 ("DBSCAN".to_string(), "DBSCAN".to_string()),
594 (
595 "AgglomerativeClustering".to_string(),
596 "Agglomerative".to_string(),
597 ),
598 ]),
599 constructor_patterns: HashMap::from([(
600 "KMeans".to_string(),
601 ConstructorPattern::New,
602 )]),
603 },
604 );
605
606 module_map.insert(
608 "sklearn.tree".to_string(),
609 ModuleMapping {
610 rust_path: "aprender::tree".to_string(),
611 is_external: true,
612 version: Some("0.14".to_string()),
613 item_map: HashMap::from([
614 (
615 "DecisionTreeClassifier".to_string(),
616 "DecisionTree".to_string(),
617 ),
618 (
619 "DecisionTreeRegressor".to_string(),
620 "DecisionTreeRegressor".to_string(),
621 ),
622 ]),
623 constructor_patterns: HashMap::new(),
624 },
625 );
626
627 module_map.insert(
629 "sklearn.ensemble".to_string(),
630 ModuleMapping {
631 rust_path: "aprender::ensemble".to_string(),
632 is_external: true,
633 version: Some("0.14".to_string()),
634 item_map: HashMap::from([
635 (
636 "RandomForestClassifier".to_string(),
637 "RandomForest".to_string(),
638 ),
639 (
640 "RandomForestRegressor".to_string(),
641 "RandomForestRegressor".to_string(),
642 ),
643 (
644 "GradientBoostingClassifier".to_string(),
645 "GradientBoosting".to_string(),
646 ),
647 ]),
648 constructor_patterns: HashMap::new(),
649 },
650 );
651
652 module_map.insert(
654 "sklearn.preprocessing".to_string(),
655 ModuleMapping {
656 rust_path: "aprender::preprocessing".to_string(),
657 is_external: true,
658 version: Some("0.14".to_string()),
659 item_map: HashMap::from([
660 ("StandardScaler".to_string(), "StandardScaler".to_string()),
661 ("MinMaxScaler".to_string(), "MinMaxScaler".to_string()),
662 ("LabelEncoder".to_string(), "LabelEncoder".to_string()),
663 ("OneHotEncoder".to_string(), "OneHotEncoder".to_string()),
664 ]),
665 constructor_patterns: HashMap::new(),
666 },
667 );
668
669 module_map.insert(
671 "sklearn.decomposition".to_string(),
672 ModuleMapping {
673 rust_path: "aprender::decomposition".to_string(),
674 is_external: true,
675 version: Some("0.14".to_string()),
676 item_map: HashMap::from([
677 ("PCA".to_string(), "PCA".to_string()),
678 ("TruncatedSVD".to_string(), "TruncatedSVD".to_string()),
679 ]),
680 constructor_patterns: HashMap::new(),
681 },
682 );
683
684 module_map.insert(
686 "sklearn.model_selection".to_string(),
687 ModuleMapping {
688 rust_path: "aprender::model_selection".to_string(),
689 is_external: true,
690 version: Some("0.14".to_string()),
691 item_map: HashMap::from([
692 (
693 "train_test_split".to_string(),
694 "train_test_split".to_string(),
695 ),
696 ("KFold".to_string(), "KFold".to_string()),
697 ("cross_val_score".to_string(), "cross_val_score".to_string()),
698 ("GridSearchCV".to_string(), "GridSearchCV".to_string()),
699 ]),
700 constructor_patterns: HashMap::new(),
701 },
702 );
703
704 module_map.insert(
706 "sklearn.metrics".to_string(),
707 ModuleMapping {
708 rust_path: "aprender::metrics".to_string(),
709 is_external: true,
710 version: Some("0.14".to_string()),
711 item_map: HashMap::from([
712 ("accuracy_score".to_string(), "accuracy".to_string()),
713 ("precision_score".to_string(), "precision".to_string()),
714 ("recall_score".to_string(), "recall".to_string()),
715 ("f1_score".to_string(), "f1".to_string()),
716 (
717 "confusion_matrix".to_string(),
718 "confusion_matrix".to_string(),
719 ),
720 ("mean_squared_error".to_string(), "mse".to_string()),
721 ("r2_score".to_string(), "r2".to_string()),
722 ]),
723 constructor_patterns: HashMap::new(),
724 },
725 );
726
727 module_map.insert(
730 "pandas".to_string(),
731 ModuleMapping {
732 rust_path: "realizar".to_string(),
733 is_external: true,
734 version: Some("0.4".to_string()),
735 item_map: HashMap::from([
736 ("DataFrame".to_string(), "DataFrame".to_string()),
738 ("Series".to_string(), "Series".to_string()),
739 ("read_csv".to_string(), "read_csv".to_string()),
741 ("read_json".to_string(), "read_json".to_string()),
742 ("read_parquet".to_string(), "read_parquet".to_string()),
743 ("to_csv".to_string(), "to_csv".to_string()),
744 ("to_json".to_string(), "to_json".to_string()),
745 ("concat".to_string(), "concat".to_string()),
747 ("merge".to_string(), "join".to_string()),
748 ("groupby".to_string(), "group_by".to_string()),
750 ("agg".to_string(), "aggregate".to_string()),
751 ("isna".to_string(), "is_null".to_string()),
753 ("fillna".to_string(), "fill_null".to_string()),
754 ("dropna".to_string(), "drop_nulls".to_string()),
755 ]),
756 constructor_patterns: HashMap::from([
757 ("DataFrame".to_string(), ConstructorPattern::New),
758 ("Series".to_string(), ConstructorPattern::New),
759 ]),
760 },
761 );
762
763 module_map.insert(
766 "scipy".to_string(),
767 ModuleMapping {
768 rust_path: "trueno".to_string(),
769 is_external: true,
770 version: Some("0.7".to_string()),
771 item_map: HashMap::new(),
772 constructor_patterns: HashMap::new(),
773 },
774 );
775
776 module_map.insert(
778 "scipy.optimize".to_string(),
779 ModuleMapping {
780 rust_path: "trueno::optimize".to_string(),
781 is_external: true,
782 version: Some("0.7".to_string()),
783 item_map: HashMap::from([
784 ("minimize".to_string(), "minimize".to_string()),
785 ("minimize_scalar".to_string(), "minimize_scalar".to_string()),
786 ("root".to_string(), "root".to_string()),
787 ("brentq".to_string(), "brentq".to_string()),
788 ("newton".to_string(), "newton".to_string()),
789 ("curve_fit".to_string(), "curve_fit".to_string()),
790 ]),
791 constructor_patterns: HashMap::new(),
792 },
793 );
794
795 module_map.insert(
797 "scipy.stats".to_string(),
798 ModuleMapping {
799 rust_path: "trueno::stats".to_string(),
800 is_external: true,
801 version: Some("0.7".to_string()),
802 item_map: HashMap::from([
803 ("norm".to_string(), "Normal".to_string()),
805 ("uniform".to_string(), "Uniform".to_string()),
806 ("expon".to_string(), "Exponential".to_string()),
807 ("poisson".to_string(), "Poisson".to_string()),
808 ("binom".to_string(), "Binomial".to_string()),
809 ("ttest_ind".to_string(), "ttest_ind".to_string()),
811 ("ttest_1samp".to_string(), "ttest_1samp".to_string()),
812 ("pearsonr".to_string(), "pearsonr".to_string()),
813 ("spearmanr".to_string(), "spearmanr".to_string()),
814 (
815 "chi2_contingency".to_string(),
816 "chi2_contingency".to_string(),
817 ),
818 ("kstest".to_string(), "kstest".to_string()),
819 ]),
820 constructor_patterns: HashMap::new(),
821 },
822 );
823
824 module_map.insert(
826 "scipy.interpolate".to_string(),
827 ModuleMapping {
828 rust_path: "trueno::interpolate".to_string(),
829 is_external: true,
830 version: Some("0.7".to_string()),
831 item_map: HashMap::from([
832 ("interp1d".to_string(), "Interp1d".to_string()),
833 ("interp2d".to_string(), "Interp2d".to_string()),
834 ("CubicSpline".to_string(), "CubicSpline".to_string()),
835 (
836 "UnivariateSpline".to_string(),
837 "UnivariateSpline".to_string(),
838 ),
839 ]),
840 constructor_patterns: HashMap::from([
841 ("Interp1d".to_string(), ConstructorPattern::New),
842 ("CubicSpline".to_string(), ConstructorPattern::New),
843 ]),
844 },
845 );
846
847 module_map.insert(
849 "scipy.signal".to_string(),
850 ModuleMapping {
851 rust_path: "trueno::signal".to_string(),
852 is_external: true,
853 version: Some("0.7".to_string()),
854 item_map: HashMap::from([
855 ("convolve".to_string(), "convolve".to_string()),
856 ("correlate".to_string(), "correlate".to_string()),
857 ("fft".to_string(), "fft".to_string()),
858 ("ifft".to_string(), "ifft".to_string()),
859 ("butter".to_string(), "butter".to_string()),
860 ("filtfilt".to_string(), "filtfilt".to_string()),
861 ]),
862 constructor_patterns: HashMap::new(),
863 },
864 );
865
866 module_map.insert(
872 "subprocess".to_string(),
873 ModuleMapping {
874 rust_path: "std::process".to_string(),
875 is_external: false,
876 version: None,
877 item_map: HashMap::from([
878 ("run".to_string(), "Command".to_string()),
880 ("Popen".to_string(), "Command".to_string()),
881 ("call".to_string(), "Command".to_string()),
882 ("check_call".to_string(), "Command".to_string()),
883 ("check_output".to_string(), "Command".to_string()),
884 ("PIPE".to_string(), "Stdio::piped".to_string()),
886 ("STDOUT".to_string(), "Stdio::inherit".to_string()),
887 ("DEVNULL".to_string(), "Stdio::null".to_string()),
888 ("CompletedProcess".to_string(), "Output".to_string()),
890 ]),
891 constructor_patterns: HashMap::from([(
892 "Command".to_string(),
893 ConstructorPattern::Method("new".to_string()),
894 )]),
895 },
896 );
897
898 module_map.insert(
901 "argparse".to_string(),
902 ModuleMapping {
903 rust_path: "clap".to_string(),
904 is_external: true,
905 version: Some("4.5".to_string()),
906 item_map: HashMap::from([
907 ("ArgumentParser".to_string(), "Parser".to_string()),
908 ]),
913 constructor_patterns: HashMap::new(),
914 },
915 );
916
917 module_map.insert(
924 "threading".to_string(),
925 ModuleMapping {
926 rust_path: "std::thread".to_string(),
927 is_external: false,
928 version: None,
929 item_map: HashMap::from([
930 ("Thread".to_string(), "spawn".to_string()),
932 ("current_thread".to_string(), "current".to_string()),
933 ("Lock".to_string(), "Mutex".to_string()),
935 ("RLock".to_string(), "Mutex".to_string()),
936 ("Event".to_string(), "Condvar".to_string()),
937 ("Condition".to_string(), "Condvar".to_string()),
938 ("Semaphore".to_string(), "Semaphore".to_string()),
939 ("BoundedSemaphore".to_string(), "Semaphore".to_string()),
940 ("Barrier".to_string(), "Barrier".to_string()),
941 ]),
942 constructor_patterns: HashMap::new(),
943 },
944 );
945
946 module_map.insert(
949 "asyncio".to_string(),
950 ModuleMapping {
951 rust_path: "tokio".to_string(),
952 is_external: true,
953 version: Some("1.35".to_string()),
954 item_map: HashMap::from([
955 ("run".to_string(), "runtime::Runtime::block_on".to_string()),
957 ("create_task".to_string(), "spawn".to_string()),
958 ("sleep".to_string(), "time::sleep".to_string()),
960 ("wait_for".to_string(), "time::timeout".to_string()),
961 ("gather".to_string(), "join!".to_string()),
963 ("wait".to_string(), "select!".to_string()),
964 ("Queue".to_string(), "sync::mpsc::channel".to_string()),
966 (
968 "get_event_loop".to_string(),
969 "runtime::Handle::current".to_string(),
970 ),
971 (
972 "new_event_loop".to_string(),
973 "runtime::Runtime::new".to_string(),
974 ),
975 ]),
976 constructor_patterns: HashMap::new(),
977 },
978 );
979
980 module_map.insert(
983 "struct".to_string(),
984 ModuleMapping {
985 rust_path: "byteorder".to_string(),
986 is_external: true,
987 version: Some("1.5".to_string()),
988 item_map: HashMap::from([
989 ("pack".to_string(), "WriteBytesExt".to_string()),
991 ("unpack".to_string(), "ReadBytesExt".to_string()),
992 ("pack_into".to_string(), "WriteBytesExt".to_string()),
993 ("unpack_from".to_string(), "ReadBytesExt".to_string()),
994 ("calcsize".to_string(), "std::mem::size_of".to_string()),
996 ("Struct".to_string(), "ByteOrder".to_string()),
998 ]),
999 constructor_patterns: HashMap::new(),
1000 },
1001 );
1002
1003 module_map.insert(
1006 "statistics".to_string(),
1007 ModuleMapping {
1008 rust_path: "statrs".to_string(),
1009 is_external: true,
1010 version: Some("0.16".to_string()),
1011 item_map: HashMap::from([
1012 (
1014 "mean".to_string(),
1015 "statistics::Statistics::mean".to_string(),
1016 ),
1017 (
1018 "median".to_string(),
1019 "statistics::Statistics::median".to_string(),
1020 ),
1021 (
1022 "mode".to_string(),
1023 "statistics::Statistics::mode".to_string(),
1024 ),
1025 (
1027 "stdev".to_string(),
1028 "statistics::Statistics::std_dev".to_string(),
1029 ),
1030 (
1031 "variance".to_string(),
1032 "statistics::Statistics::variance".to_string(),
1033 ),
1034 (
1035 "pstdev".to_string(),
1036 "statistics::Statistics::population_std_dev".to_string(),
1037 ),
1038 (
1039 "pvariance".to_string(),
1040 "statistics::Statistics::population_variance".to_string(),
1041 ),
1042 (
1044 "quantiles".to_string(),
1045 "statistics::Statistics::percentile".to_string(),
1046 ),
1047 ]),
1048 constructor_patterns: HashMap::new(),
1049 },
1050 );
1051
1052 module_map.insert(
1059 "logging".to_string(),
1060 ModuleMapping {
1061 rust_path: "log".to_string(),
1062 is_external: true,
1063 version: Some("0.4".to_string()),
1064 item_map: HashMap::from([
1065 ("debug".to_string(), "debug!".to_string()),
1067 ("info".to_string(), "info!".to_string()),
1068 ("warning".to_string(), "warn!".to_string()),
1069 ("warn".to_string(), "warn!".to_string()),
1070 ("error".to_string(), "error!".to_string()),
1071 ("critical".to_string(), "error!".to_string()),
1072 ("basicConfig".to_string(), "env_logger::init".to_string()),
1074 ("getLogger".to_string(), "log::logger".to_string()),
1075 ("DEBUG".to_string(), "log::Level::Debug".to_string()),
1077 ("INFO".to_string(), "log::Level::Info".to_string()),
1078 ("WARNING".to_string(), "log::Level::Warn".to_string()),
1079 ("ERROR".to_string(), "log::Level::Error".to_string()),
1080 ("CRITICAL".to_string(), "log::Level::Error".to_string()),
1081 ]),
1082 constructor_patterns: HashMap::new(),
1083 },
1084 );
1085
1086 module_map.insert(
1089 "configparser".to_string(),
1090 ModuleMapping {
1091 rust_path: "config".to_string(),
1092 is_external: true,
1093 version: Some("0.14".to_string()),
1094 item_map: HashMap::from([
1095 ("ConfigParser".to_string(), "Config".to_string()),
1096 ("RawConfigParser".to_string(), "Config".to_string()),
1097 ("SafeConfigParser".to_string(), "Config".to_string()),
1098 ]),
1099 constructor_patterns: HashMap::from([(
1100 "Config".to_string(),
1101 ConstructorPattern::Method("builder".to_string()),
1102 )]),
1103 },
1104 );
1105
1106 module_map.insert(
1109 "unittest".to_string(),
1110 ModuleMapping {
1111 rust_path: "".to_string(), is_external: false,
1113 version: None,
1114 item_map: HashMap::from([
1115 ("TestCase".to_string(), "".to_string()),
1117 ("assertEqual".to_string(), "assert_eq!".to_string()),
1119 ("assertNotEqual".to_string(), "assert_ne!".to_string()),
1120 ("assertTrue".to_string(), "assert!".to_string()),
1121 ("assertFalse".to_string(), "assert!".to_string()),
1122 ("assertIsNone".to_string(), "assert!".to_string()),
1123 ("assertIsNotNone".to_string(), "assert!".to_string()),
1124 ("assertIn".to_string(), "assert!".to_string()),
1125 ("assertNotIn".to_string(), "assert!".to_string()),
1126 ("assertRaises".to_string(), "assert!".to_string()),
1127 ("main".to_string(), "".to_string()), ]),
1129 constructor_patterns: HashMap::new(),
1130 },
1131 );
1132
1133 module_map.insert(
1136 "traceback".to_string(),
1137 ModuleMapping {
1138 rust_path: "backtrace".to_string(),
1139 is_external: true,
1140 version: Some("0.3".to_string()),
1141 item_map: HashMap::from([
1142 ("print_exc".to_string(), "Backtrace::capture".to_string()),
1143 ("format_exc".to_string(), "Backtrace::capture".to_string()),
1144 ("print_tb".to_string(), "Backtrace::capture".to_string()),
1145 ("format_tb".to_string(), "Backtrace::capture".to_string()),
1146 ("extract_tb".to_string(), "Backtrace::capture".to_string()),
1147 ]),
1148 constructor_patterns: HashMap::new(),
1149 },
1150 );
1151
1152 module_map.insert(
1155 "contextlib".to_string(),
1156 ModuleMapping {
1157 rust_path: "".to_string(), is_external: false,
1159 version: None,
1160 item_map: HashMap::from([
1161 ("contextmanager".to_string(), "".to_string()),
1163 ("closing".to_string(), "".to_string()),
1164 ("suppress".to_string(), "".to_string()),
1165 ("nullcontext".to_string(), "".to_string()),
1166 ]),
1167 constructor_patterns: HashMap::new(),
1168 },
1169 );
1170
1171 Self { module_map }
1172 }
1173
1174 pub fn map_import(&self, import: &Import) -> Vec<RustImport> {
1193 let mut rust_imports = Vec::new();
1194
1195 if let Some(mapping) = self.module_map.get(&import.module) {
1196 if import.items.is_empty() {
1198 if !mapping.rust_path.is_empty() {
1201 if import.module == "argparse" {
1203 rust_imports.push(RustImport {
1205 path: format!("{}::Parser", mapping.rust_path),
1206 alias: None,
1207 is_external: mapping.is_external,
1208 });
1209 } else {
1210 rust_imports.push(RustImport {
1212 path: mapping.rust_path.clone(),
1213 alias: Some(import.module.clone()),
1214 is_external: mapping.is_external,
1215 });
1216 }
1217 } else {
1218 rust_imports.push(RustImport {
1220 path: format!("// Python import: {} (no Rust equivalent)", import.module),
1221 alias: None,
1222 is_external: false,
1223 });
1224 }
1225 } else {
1226 for item in &import.items {
1228 match item {
1229 ImportItem::Named(name) => {
1230 if let Some(rust_name) = mapping.item_map.get(name) {
1231 rust_imports.push(RustImport {
1232 path: format!("{}::{}", mapping.rust_path, rust_name),
1233 alias: None,
1234 is_external: mapping.is_external,
1235 });
1236 } else {
1237 rust_imports.push(RustImport {
1239 path: format!("{}::{}", mapping.rust_path, name),
1240 alias: None,
1241 is_external: mapping.is_external,
1242 });
1243 }
1244 }
1245 ImportItem::Aliased { name, alias } => {
1246 if let Some(rust_name) = mapping.item_map.get(name) {
1247 rust_imports.push(RustImport {
1248 path: format!("{}::{}", mapping.rust_path, rust_name),
1249 alias: Some(alias.clone()),
1250 is_external: mapping.is_external,
1251 });
1252 } else {
1253 rust_imports.push(RustImport {
1254 path: format!("{}::{}", mapping.rust_path, name),
1255 alias: Some(alias.clone()),
1256 is_external: mapping.is_external,
1257 });
1258 }
1259 }
1260 }
1261 }
1262 }
1263 } else {
1264 rust_imports.push(RustImport {
1266 path: format!(
1267 "// NOTE: Map Python module '{}' (tracked in DEPYLER-0424)",
1268 import.module
1269 ),
1270 alias: None,
1271 is_external: false,
1272 });
1273 }
1274
1275 rust_imports
1276 }
1277
1278 pub fn get_dependencies(&self, imports: &[Import]) -> Vec<(String, String)> {
1303 let mut deps = Vec::new();
1304 let mut seen = std::collections::HashSet::new();
1305
1306 for import in imports {
1307 if let Some(mapping) = self.module_map.get(&import.module) {
1308 if mapping.is_external && !seen.contains(&mapping.rust_path) {
1309 seen.insert(&mapping.rust_path);
1310 if let Some(version) = &mapping.version {
1311 deps.push((mapping.rust_path.clone(), version.clone()));
1312 }
1313 }
1314 }
1315 }
1316
1317 deps
1318 }
1319
1320 pub fn get_mapping(&self, module_name: &str) -> Option<&ModuleMapping> {
1336 self.module_map.get(module_name)
1337 }
1338}
1339
1340#[derive(Debug, Clone)]
1341pub struct RustImport {
1342 pub path: String,
1343 pub alias: Option<String>,
1344 pub is_external: bool,
1345}
1346
1347impl Default for ModuleMapper {
1348 fn default() -> Self {
1349 Self::new()
1350 }
1351}