• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

TEN-framework / ten-framework / 22619347703

03 Mar 2026 10:42AM UTC coverage: 58.709%. First build
22619347703

Pull #2076

github

web-flow
Merge 231d157c9 into ebc85564f
Pull Request #2076: feat: quick start demo on windows

0 of 162 new or added lines in 6 files covered. (0.0%)

53169 of 90563 relevant lines covered (58.71%)

737353.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/core/src/ten_manager/src/check_env/check_python.rs
1
//
2
// Copyright © 2025 Agora
3
// This file is part of TEN Framework, an open source project.
4
// Licensed under the Apache License, Version 2.0, with certain conditions.
5
// Refer to the "LICENSE" file in the root directory for more information.
6
//
7
use anyhow::Result;
8

9
use super::types::{CheckStatus, PythonCheckResult, Suggestion, ToolInfo};
10

11
/// Check Python development environment (python3 command, version == 3.10).
12
/// Returns structured result about Python installation.
13
pub fn check() -> Result<PythonCheckResult> {
×
14
    let mut python_info = None;
×
15
    let mut pip_info = None;
×
16
    let mut is_correct_version = false;
×
17
    let mut suggestions = Vec::new();
×
18

19
    // Check if python3 command exists
20
    let python_check = std::process::Command::new("python3").arg("--version").output();
×
21

22
    match python_check {
×
23
        Ok(output) if output.status.success() => {
×
24
            // Parse version from output
25
            let version_str = String::from_utf8_lossy(&output.stdout);
×
26
            let version_str = version_str.trim();
×
27

28
            // Extract version number (format: "Python 3.10.12")
29
            if let Some(version_part) = version_str.strip_prefix("Python ") {
×
30
                // Parse major.minor version
31
                let version_parts: Vec<&str> = version_part.split('.').collect();
×
32
                if version_parts.len() >= 2 {
×
33
                    if let (Ok(major), Ok(minor)) =
×
34
                        (version_parts[0].parse::<u32>(), version_parts[1].parse::<u32>())
×
35
                    {
36
                        // Check if version == 3.10
37
                        if major == 3 && minor == 10 {
×
38
                            // Find python3 path
NEW
39
                            let path = if cfg!(windows) {
×
NEW
40
                                std::process::Command::new("where.exe").arg("python3").output().ok()
×
NEW
41
                                    .and_then(|output| {
×
NEW
42
                                        if output.status.success() {
×
NEW
43
                                            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
44
                                        } else {
NEW
45
                                            None
×
46
                                        }
NEW
47
                                    })
×
48
                            } else {
NEW
49
                                std::process::Command::new("which").arg("python3").output().ok()
×
NEW
50
                                    .and_then(|output| {
×
NEW
51
                                        if output.status.success() {
×
NEW
52
                                            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
53
                                        } else {
NEW
54
                                            None
×
55
                                        }
NEW
56
                                    })
×
57
                            };
58

59
                            python_info = Some(ToolInfo {
×
60
                                name: "python3".to_string(),
×
61
                                version: Some(version_part.to_string()),
×
62
                                path,
×
63
                                status: CheckStatus::Ok,
×
64
                                notes: vec![],
×
65
                            });
×
66

67
                            is_correct_version = true;
×
68

69
                            // Check pip3
70
                            let pip_check =
×
71
                                std::process::Command::new("pip3").arg("--version").output();
×
72
                            if let Ok(pip_output) = pip_check {
×
73
                                if pip_output.status.success() {
×
74
                                    let pip_version = String::from_utf8_lossy(&pip_output.stdout);
×
75
                                    let version_info =
×
76
                                        pip_version.split_whitespace().nth(1).map(|s| s.to_string());
×
77

78
                                    pip_info = Some(ToolInfo {
×
79
                                        name: "pip3".to_string(),
×
80
                                        version: version_info,
×
81
                                        path: None,
×
82
                                        status: CheckStatus::Ok,
×
83
                                        notes: vec![],
×
84
                                    });
×
85
                                }
×
86
                            }
×
87
                        } else {
NEW
88
                            let path = if cfg!(windows) {
×
NEW
89
                                std::process::Command::new("where.exe").arg("python3").output().ok()
×
NEW
90
                                    .and_then(|output| {
×
NEW
91
                                        if output.status.success() {
×
NEW
92
                                            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
93
                                        } else {
NEW
94
                                            None
×
95
                                        }
NEW
96
                                    })
×
97
                            } else {
NEW
98
                                std::process::Command::new("which").arg("python3").output().ok()
×
NEW
99
                                    .and_then(|output| {
×
NEW
100
                                        if output.status.success() {
×
NEW
101
                                            Some(String::from_utf8_lossy(&output.stdout).trim().to_string())
×
102
                                        } else {
NEW
103
                                            None
×
104
                                        }
NEW
105
                                    })
×
106
                            };
107

108
                            python_info = Some(ToolInfo {
×
109
                                name: "python3".to_string(),
×
110
                                version: Some(version_part.to_string()),
×
111
                                path,
×
112
                                status: CheckStatus::Warning,
×
113
                                notes: vec!["TEN Framework only supports Python 3.10".to_string()],
×
114
                            });
×
115

116
                            suggestions.push(Suggestion {
×
117
                                issue: format!("Python {} installed, but TEN Framework only supports Python 3.10", version_part),
×
118
                                command: Some("pyenv install 3.10.18 && pyenv local 3.10.18".to_string()),
×
119
                                help_text: Some("Please use pyenv to install Python 3.10".to_string()),
×
120
                            });
×
121
                        }
122
                    }
×
123
                }
×
124
            }
×
125

126
            // If we can't parse the version, still report it
127
            if python_info.is_none() {
×
128
                python_info = Some(ToolInfo {
×
129
                    name: "python3".to_string(),
×
130
                    version: Some(version_str.to_string()),
×
131
                    path: None,
×
132
                    status: CheckStatus::Warning,
×
133
                    notes: vec!["Unable to parse version".to_string()],
×
134
                });
×
135

×
136
                suggestions.push(Suggestion {
×
137
                    issue: "Unable to parse Python version".to_string(),
×
138
                    command: None,
×
139
                    help_text: Some("Please ensure Python 3.10 is installed".to_string()),
×
140
                });
×
141
            }
×
142
        }
143
        _ => {
×
144
            python_info = Some(ToolInfo {
×
145
                name: "python3".to_string(),
×
146
                version: None,
×
147
                path: None,
×
148
                status: CheckStatus::Error,
×
149
                notes: vec!["Not found".to_string()],
×
150
            });
×
151

×
152
            suggestions.push(Suggestion {
×
153
                issue: "Python not found".to_string(),
×
154
                command: Some("pyenv install 3.10.18 && pyenv local 3.10.18".to_string()),
×
155
                help_text: Some("Please install Python 3.10 using pyenv (recommended)".to_string()),
×
156
            });
×
157
        }
×
158
    }
159

160
    // Determine overall status
161
    let status = if is_correct_version {
×
162
        CheckStatus::Ok
×
163
    } else if python_info.as_ref().map(|p| p.version.is_some()).unwrap_or(false) {
×
164
        CheckStatus::Warning
×
165
    } else {
166
        CheckStatus::Error
×
167
    };
168

169
    Ok(PythonCheckResult {
×
170
        python: python_info,
×
171
        pip: pip_info,
×
172
        is_correct_version,
×
173
        status,
×
174
        suggestions,
×
175
    })
×
176
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc