depyler-core 3.13.0

Core transpilation engine for the Depyler Python-to-Rust transpiler
Documentation
use crate::hir::{Import, ImportItem};
use crate::module_mapper::{ModuleMapper, ModuleMapping, RustImport};
use std::collections::HashMap;

#[test]
fn test_module_mapper_creation() {
    let mapper = ModuleMapper::new();
    // Should create without panic
    assert!(mapper.get_mapping("os").is_some());
    assert!(mapper.get_mapping("sys").is_some());
    assert!(mapper.get_mapping("json").is_some());
}

#[test]
fn test_default_trait() {
    let mapper1 = ModuleMapper::new();
    let mapper2 = ModuleMapper::default();

    // Both should have the same mappings
    assert_eq!(
        mapper1.get_mapping("os").unwrap().rust_path,
        mapper2.get_mapping("os").unwrap().rust_path
    );
}

#[test]
fn test_stdlib_mappings() {
    let mapper = ModuleMapper::new();

    // Test os module
    let os_mapping = mapper.get_mapping("os").unwrap();
    assert_eq!(os_mapping.rust_path, "std");
    assert!(!os_mapping.is_external);
    assert!(os_mapping.version.is_none());
    assert_eq!(
        os_mapping.item_map.get("getcwd").unwrap(),
        "env::current_dir"
    );
    assert_eq!(os_mapping.item_map.get("environ").unwrap(), "env::vars");

    // Test sys module
    let sys_mapping = mapper.get_mapping("sys").unwrap();
    assert_eq!(sys_mapping.rust_path, "std");
    assert_eq!(sys_mapping.item_map.get("argv").unwrap(), "env::args");
    assert_eq!(sys_mapping.item_map.get("exit").unwrap(), "process::exit");

    // Test math module
    let math_mapping = mapper.get_mapping("math").unwrap();
    assert_eq!(math_mapping.rust_path, "std::f64");
    assert_eq!(math_mapping.item_map.get("sqrt").unwrap(), "sqrt");
    assert_eq!(math_mapping.item_map.get("pi").unwrap(), "consts::PI");
}

#[test]
fn test_external_crate_mappings() {
    let mapper = ModuleMapper::new();

    // Test json module
    let json_mapping = mapper.get_mapping("json").unwrap();
    assert_eq!(json_mapping.rust_path, "serde_json");
    assert!(json_mapping.is_external);
    assert_eq!(json_mapping.version.as_ref().unwrap(), "1.0");
    assert_eq!(json_mapping.item_map.get("loads").unwrap(), "from_str");

    // Test regex module
    let re_mapping = mapper.get_mapping("re").unwrap();
    assert_eq!(re_mapping.rust_path, "regex");
    assert!(re_mapping.is_external);
    assert_eq!(re_mapping.version.as_ref().unwrap(), "1.0");
    assert_eq!(re_mapping.item_map.get("compile").unwrap(), "Regex::new");

    // Test chrono module
    let datetime_mapping = mapper.get_mapping("datetime").unwrap();
    assert_eq!(datetime_mapping.rust_path, "chrono");
    assert!(datetime_mapping.is_external);
    assert_eq!(datetime_mapping.version.as_ref().unwrap(), "0.4");
}

#[test]
fn test_typing_module_mapping() {
    let mapper = ModuleMapper::new();

    let typing_mapping = mapper.get_mapping("typing").unwrap();
    assert_eq!(typing_mapping.rust_path, "");
    assert!(!typing_mapping.is_external);
    assert_eq!(typing_mapping.item_map.get("List").unwrap(), "Vec");
    assert_eq!(typing_mapping.item_map.get("Dict").unwrap(), "HashMap");
    assert_eq!(typing_mapping.item_map.get("Optional").unwrap(), "Option");
}

#[test]
fn test_map_simple_import() {
    let mapper = ModuleMapper::new();

    // Test import with named items
    let import = Import {
        module: "os".to_string(),
        items: vec![ImportItem::Named("getcwd".to_string())],
    };

    let rust_imports = mapper.map_import(&import);
    assert_eq!(rust_imports.len(), 1);
    assert_eq!(rust_imports[0].path, "std::env::current_dir");
    assert!(!rust_imports[0].is_external);
    assert!(rust_imports[0].alias.is_none());
}

#[test]
fn test_map_aliased_import() {
    let mapper = ModuleMapper::new();

    let import = Import {
        module: "json".to_string(),
        items: vec![ImportItem::Aliased {
            name: "loads".to_string(),
            alias: "parse_json".to_string(),
        }],
    };

    let rust_imports = mapper.map_import(&import);
    assert_eq!(rust_imports.len(), 1);
    assert_eq!(rust_imports[0].path, "serde_json::from_str");
    assert!(rust_imports[0].is_external);
    assert_eq!(rust_imports[0].alias.as_ref().unwrap(), "parse_json");
}

#[test]
fn test_map_whole_module_import() {
    let mapper = ModuleMapper::new();

    // Test "import os" style
    let import = Import {
        module: "os".to_string(),
        items: vec![],
    };

    let rust_imports = mapper.map_import(&import);
    assert_eq!(rust_imports.len(), 1);
    assert!(rust_imports[0].path.contains("Python import: os"));
}

#[test]
fn test_map_unknown_module() {
    let mapper = ModuleMapper::new();

    let import = Import {
        module: "unknown_module".to_string(),
        items: vec![ImportItem::Named("something".to_string())],
    };

    let rust_imports = mapper.map_import(&import);
    assert_eq!(rust_imports.len(), 1);
    assert!(rust_imports[0].path.contains("TODO: Map Python module"));
}

#[test]
fn test_map_multiple_items() {
    let mapper = ModuleMapper::new();

    let import = Import {
        module: "os".to_string(),
        items: vec![
            ImportItem::Named("getcwd".to_string()),
            ImportItem::Named("environ".to_string()),
            ImportItem::Aliased {
                name: "path".to_string(),
                alias: "os_path".to_string(),
            },
        ],
    };

    let rust_imports = mapper.map_import(&import);
    assert_eq!(rust_imports.len(), 3);
    assert_eq!(rust_imports[0].path, "std::env::current_dir");
    assert_eq!(rust_imports[1].path, "std::env::vars");
    assert_eq!(rust_imports[2].path, "std::path::Path");
    assert_eq!(rust_imports[2].alias.as_ref().unwrap(), "os_path");
}

#[test]
fn test_get_dependencies() {
    let mapper = ModuleMapper::new();

    let imports = vec![
        Import {
            module: "json".to_string(),
            items: vec![ImportItem::Named("loads".to_string())],
        },
        Import {
            module: "re".to_string(),
            items: vec![ImportItem::Named("compile".to_string())],
        },
        Import {
            module: "os".to_string(),
            items: vec![ImportItem::Named("getcwd".to_string())],
        },
        Import {
            module: "json".to_string(), // Duplicate, should be deduped
            items: vec![ImportItem::Named("dumps".to_string())],
        },
    ];

    let deps = mapper.get_dependencies(&imports);
    assert_eq!(deps.len(), 2); // json and re (os is stdlib)
    assert!(deps.contains(&("serde_json".to_string(), "1.0".to_string())));
    assert!(deps.contains(&("regex".to_string(), "1.0".to_string())));
}

#[test]
fn test_complex_module_paths() {
    let mapper = ModuleMapper::new();

    // Test os.path
    let os_path_mapping = mapper.get_mapping("os.path").unwrap();
    assert_eq!(os_path_mapping.rust_path, "std::path");
    assert_eq!(os_path_mapping.item_map.get("join").unwrap(), "Path::join");

    // Test urllib.parse
    let urllib_mapping = mapper.get_mapping("urllib.parse").unwrap();
    assert_eq!(urllib_mapping.rust_path, "url");
    assert!(urllib_mapping.is_external);
}

#[test]
fn test_collections_mapping() {
    let mapper = ModuleMapper::new();

    let collections_mapping = mapper.get_mapping("collections").unwrap();
    assert_eq!(collections_mapping.rust_path, "std::collections");
    assert_eq!(
        collections_mapping.item_map.get("deque").unwrap(),
        "VecDeque"
    );
    assert_eq!(
        collections_mapping.item_map.get("OrderedDict").unwrap(),
        "IndexMap"
    );
}

#[test]
fn test_itertools_mapping() {
    let mapper = ModuleMapper::new();

    let itertools_mapping = mapper.get_mapping("itertools").unwrap();
    assert_eq!(itertools_mapping.rust_path, "itertools");
    assert!(itertools_mapping.is_external);
    assert_eq!(itertools_mapping.version.as_ref().unwrap(), "0.11");
    assert_eq!(itertools_mapping.item_map.get("chain").unwrap(), "chain");
    assert_eq!(
        itertools_mapping.item_map.get("product").unwrap(),
        "iproduct"
    );
}

#[test]
fn test_unmapped_item_fallback() {
    let mapper = ModuleMapper::new();

    // Test an item that's not in the item_map
    let import = Import {
        module: "os".to_string(),
        items: vec![ImportItem::Named("unmapped_function".to_string())],
    };

    let rust_imports = mapper.map_import(&import);
    assert_eq!(rust_imports.len(), 1);
    // Should use direct mapping when not found in item_map
    assert_eq!(rust_imports[0].path, "std::unmapped_function");
}

#[test]
fn test_crypto_mappings() {
    let mapper = ModuleMapper::new();

    // Test hashlib
    let hashlib_mapping = mapper.get_mapping("hashlib").unwrap();
    assert_eq!(hashlib_mapping.rust_path, "sha2");
    assert!(hashlib_mapping.is_external);
    assert_eq!(hashlib_mapping.item_map.get("sha256").unwrap(), "Sha256");

    // Test base64
    let base64_mapping = mapper.get_mapping("base64").unwrap();
    assert_eq!(base64_mapping.rust_path, "base64");
    assert!(base64_mapping.is_external);
    assert_eq!(base64_mapping.item_map.get("b64encode").unwrap(), "encode");
}

#[test]
fn test_tempfile_mapping() {
    let mapper = ModuleMapper::new();

    let tempfile_mapping = mapper.get_mapping("tempfile").unwrap();
    assert_eq!(tempfile_mapping.rust_path, "tempfile");
    assert!(tempfile_mapping.is_external);
    assert_eq!(
        tempfile_mapping.item_map.get("NamedTemporaryFile").unwrap(),
        "NamedTempFile"
    );
}

#[test]
fn test_module_mapping_clone() {
    let mapping = ModuleMapping {
        rust_path: "test".to_string(),
        is_external: true,
        version: Some("1.0".to_string()),
        item_map: HashMap::from([("foo".to_string(), "bar".to_string())]),
    };

    let cloned = mapping.clone();
    assert_eq!(cloned.rust_path, mapping.rust_path);
    assert_eq!(cloned.is_external, mapping.is_external);
    assert_eq!(cloned.version, mapping.version);
    assert_eq!(cloned.item_map, mapping.item_map);
}

#[test]
fn test_rust_import_struct() {
    let import = RustImport {
        path: "std::env::args".to_string(),
        alias: Some("cmdline_args".to_string()),
        is_external: false,
    };

    assert_eq!(import.path, "std::env::args");
    assert_eq!(import.alias.as_ref().unwrap(), "cmdline_args");
    assert!(!import.is_external);

    // Test Debug trait
    let debug_str = format!("{:?}", import);
    assert!(debug_str.contains("RustImport"));
    assert!(debug_str.contains("cmdline_args"));
}

#[test]
fn test_empty_imports_dependencies() {
    let mapper = ModuleMapper::new();
    let imports: Vec<Import> = vec![];
    let deps = mapper.get_dependencies(&imports);
    assert!(deps.is_empty());
}