python_proto_importer/verification/
script_generator.rs

1/// Create a comprehensive Python import test script
2///
3/// This function generates a Python script that attempts to import all provided modules
4/// and reports success/failure statistics to stderr. The script handles various types
5/// of import errors and provides detailed error reporting.
6pub fn create_import_test_script(package_name: &str, modules: &[String]) -> String {
7    let mut script = String::new();
8    script.push_str("import sys\n");
9    script.push_str("import importlib\n");
10    script.push_str("import traceback\n");
11    script.push('\n');
12    script.push_str("failed = []\n");
13    script.push_str("succeeded = []\n");
14    script.push('\n');
15
16    for module in modules {
17        let full_module = if package_name.is_empty() {
18            module.clone()
19        } else {
20            format!("{}.{}", package_name, module)
21        };
22
23        script.push_str(&format!(
24            r#"
25# Test module: {} -> {}
26try:
27    mod = importlib.import_module('{}')
28    succeeded.append('{}')
29except ImportError as e:
30    import_error = str(e)
31    if "relative import" in import_error.lower():
32        import_error += " (relative import context issue)"
33    failed.append(('{}', 'ImportError: ' + import_error))
34except ModuleNotFoundError as e:
35    failed.append(('{}', 'ModuleNotFoundError: ' + str(e)))
36except SyntaxError as e:
37    failed.append(('{}', 'SyntaxError: ' + str(e) + ' at line ' + str(e.lineno or 'unknown')))
38except Exception as e:
39    tb = traceback.format_exc()
40    failed.append(('{}', 'Exception: ' + type(e).__name__ + ': ' + str(e)))
41"#,
42            module, full_module, full_module, module, module, module, module, module
43        ));
44    }
45
46    script.push('\n');
47    script.push_str("print(f'IMPORT_TEST_SUMMARY:succeeded={len(succeeded)},failed={len(failed)},total={len(succeeded)+len(failed)}', file=sys.stderr)\n");
48    script.push('\n');
49    script.push_str("if failed:\n");
50    script.push_str("    for module, error in failed:\n");
51    script.push_str("        print(f'IMPORT_ERROR:{module}:{error}', file=sys.stderr)\n");
52    script.push_str("    sys.exit(1)\n");
53    script.push_str("else:\n");
54    script.push_str(
55        "    print('IMPORT_TEST_SUCCESS:all_modules_imported_successfully', file=sys.stderr)\n",
56    );
57
58    script
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_create_import_test_script_empty_modules() {
67        let script = create_import_test_script("test_package", &[]);
68
69        assert!(script.contains("import sys"));
70        assert!(script.contains("import importlib"));
71        assert!(script.contains("import traceback"));
72        assert!(script.contains("failed = []"));
73        assert!(script.contains("succeeded = []"));
74        assert!(script.contains("IMPORT_TEST_SUMMARY"));
75        assert!(script.contains("IMPORT_TEST_SUCCESS"));
76    }
77
78    #[test]
79    fn test_create_import_test_script_single_module() {
80        let modules = vec!["test_module".to_string()];
81        let script = create_import_test_script("test_package", &modules);
82
83        assert!(script.contains("test_module -> test_package.test_module"));
84        assert!(script.contains("importlib.import_module('test_package.test_module')"));
85        assert!(script.contains("succeeded.append('test_module')"));
86        assert!(script.contains("ImportError"));
87        assert!(script.contains("ModuleNotFoundError"));
88        assert!(script.contains("SyntaxError"));
89    }
90
91    #[test]
92    fn test_create_import_test_script_multiple_modules() {
93        let modules = vec![
94            "module1".to_string(),
95            "module2".to_string(),
96            "subpkg.module3".to_string(),
97        ];
98        let script = create_import_test_script("mypackage", &modules);
99
100        assert!(script.contains("module1 -> mypackage.module1"));
101        assert!(script.contains("module2 -> mypackage.module2"));
102        assert!(script.contains("subpkg.module3 -> mypackage.subpkg.module3"));
103        assert!(script.contains("importlib.import_module('mypackage.module1')"));
104        assert!(script.contains("importlib.import_module('mypackage.module2')"));
105        assert!(script.contains("importlib.import_module('mypackage.subpkg.module3')"));
106    }
107
108    #[test]
109    fn test_create_import_test_script_empty_package_name() {
110        let modules = vec!["standalone_module".to_string()];
111        let script = create_import_test_script("", &modules);
112
113        assert!(script.contains("standalone_module -> standalone_module"));
114        assert!(script.contains("importlib.import_module('standalone_module')"));
115        assert!(script.contains("succeeded.append('standalone_module')"));
116    }
117
118    #[test]
119    fn test_create_import_test_script_error_handling() {
120        let modules = vec!["test_module".to_string()];
121        let script = create_import_test_script("pkg", &modules);
122
123        assert!(script.contains("relative import"));
124        assert!(script.contains("relative import context issue"));
125        assert!(script.contains("failed.append"));
126        assert!(script.contains("ImportError:"));
127        assert!(script.contains("ModuleNotFoundError:"));
128        assert!(script.contains("SyntaxError:"));
129        assert!(script.contains("Exception:"));
130    }
131
132    #[test]
133    fn test_create_import_test_script_output_format() {
134        let modules = vec!["mod1".to_string(), "mod2".to_string()];
135        let script = create_import_test_script("pkg", &modules);
136
137        assert!(script.contains("IMPORT_TEST_SUMMARY:succeeded="));
138        assert!(script.contains(",failed="));
139        assert!(script.contains(",total="));
140        assert!(script.contains("IMPORT_ERROR:"));
141        assert!(script.contains("sys.exit(1)"));
142        assert!(script.contains("IMPORT_TEST_SUCCESS:all_modules_imported_successfully"));
143    }
144}