Summary
This feature request documents critical gaps in Python stdlib module support that prevent depyler from transpiling real-world CLI tools. Based on comprehensive testing with 11 examples, only 36.4% of common CLI patterns are currently supported.
The "Essential 3" features needed to unlock ~70% of real-world tools are:
- os.environ - Environment variable access
- os.path - Path operations
- Context managers -
with statement
Current Status
Depyler Compatibility: 4/11 examples (36.4%)
✅ What Works (4/11)
example_simple - Basic argparse
example_flags - Boolean flags
example_positional - Positional arguments
example_subcommands - Subcommands (FIXED in DEPYLER-0396!)
❌ What Doesn't Work (7/11)
| Example |
Blocker |
Priority |
Impact |
example_environment |
os, sys, platform modules |
🔴 P0-CRITICAL |
90% of tools |
example_io_streams |
context managers, stdin iteration |
🟠 P1-HIGH |
70% of tools |
example_regex |
re module |
🟠 P1-HIGH |
50% of tools |
example_subprocess |
subprocess module |
🟠 P1-HIGH |
50% of tools |
example_config |
global constants, subparser vars |
🟡 P2-MEDIUM |
40% of tools |
example_complex |
type inference, validators |
🟡 P2-MEDIUM |
20% of tools |
example_stdlib |
expression types |
🟡 P2-MEDIUM |
20% of tools |
Priority 0 - CRITICAL: os Module Support
Impact: Blocks 90%+ of real-world CLI tools
1. os.environ - Environment Variables
Python patterns needed:
# Get with default
home = os.environ.get('HOME', '/default')
# Direct access
user = os.environ['USER']
# Check existence
if 'DEBUG' in os.environ:
enable_debug()
# Set variable
os.environ['MY_VAR'] = 'value'
Rust equivalents:
use std::env;
// Get with default
let home = env::var("HOME").unwrap_or("/default".to_string());
// Direct access (returns Result)
let user = env::var("USER").expect("USER not set");
// Check existence
if env::var("DEBUG").is_ok() {
enable_debug();
}
// Set variable
env::set_var("MY_VAR", "value");
Example use case (examples/example_environment/env_info.py):
python3 env_info.py env HOME
→ HOME=/home/noah
Current error: Expression type not yet supported
2. os.path - Path Operations
Python patterns needed:
# Join paths
config_path = os.path.join(base_dir, 'config.json')
# Check existence
if os.path.exists(path):
process_file(path)
# Expand home directory
config = os.path.expanduser('~/.myapp/config')
# Path components
dir_name = os.path.dirname('/path/to/file')
base_name = os.path.basename('/path/to/file')
abs_path = os.path.abspath('relative/path')
# Type checks
is_file = os.path.isfile(path)
is_dir = os.path.isdir(path)
Rust equivalents:
use std::path::{Path, PathBuf};
// Join paths
let config_path = Path::new(&base_dir).join("config.json");
// Check existence
if Path::new(&path).exists() {
process_file(&path);
}
// Expand home directory (needs external crate)
use dirs;
let config = dirs::home_dir().unwrap().join(".myapp/config");
// Path components
let dir_name = Path::new("/path/to/file").parent();
let base_name = Path::new("/path/to/file").file_name();
let abs_path = std::fs::canonicalize("relative/path")?;
// Type checks
let is_file = Path::new(&path).is_file();
let is_dir = Path::new(&path).is_dir();
Example use case:
python3 env_info.py path ~/.bashrc
→ Exists: True
→ Is file: True
python3 env_info.py join /home user config.json
→ Joined path: /home/user/config.json
Current error: Expression type not yet supported
3. sys Module - System Information
Python patterns needed:
# Platform detection
if sys.platform == 'linux':
use_linux_features()
# Exit with code
sys.exit(1)
# Command line args (usually handled by argparse)
args = sys.argv[1:]
Rust equivalents:
// Platform detection (compile-time)
#[cfg(target_os = "linux")]
fn use_linux_features() { }
// Exit with code
std::process::exit(1);
// Command line args
let args: Vec<String> = std::env::args().skip(1).collect();
Example use case:
python3 env_info.py system
→ Platform: linux
→ OS: Linux
→ Architecture: x86_64
4. platform Module - System Introspection
Python patterns needed:
os_name = platform.system() # 'Linux', 'Darwin', 'Windows'
arch = platform.machine() # 'x86_64', 'arm64'
py_version = platform.python_version()
Rust equivalents:
use std::env;
let os_name = env::consts::OS; // "linux", "macos", "windows"
let arch = env::consts::ARCH; // "x86_64", "aarch64"
// Python version not applicable in Rust
Priority 1 - HIGH: I/O and Text Processing
5. Context Managers - with Statement
Python patterns needed:
# File operations
with open(path, 'r') as f:
content = f.read()
# Write to file
with open(path, 'w') as f:
f.write(data)
# Append mode
with open(path, 'a') as f:
f.write(line)
Rust equivalents (RAII handles cleanup automatically):
use std::fs::File;
use std::io::{Read, Write};
// Read file
{
let mut f = File::open(path)?;
let mut content = String::new();
f.read_to_string(&mut content)?;
} // File closed automatically
// Write to file
{
let mut f = File::create(path)?;
f.write_all(data.as_bytes())?;
}
// Append mode
use std::fs::OpenOptions;
{
let mut f = OpenOptions::new().append(true).open(path)?;
f.write_all(line.as_bytes())?;
}
Example use case (examples/example_io_streams/stream_processor.py):
python3 stream_processor.py write test.txt "Hello"
→ Wrote to test.txt
python3 stream_processor.py read test.txt
→ Hello
Current error: Expression type not yet supported
6. stdin Iteration
Python patterns needed:
# Line-by-line iteration
for line in sys.stdin:
process(line.strip())
# Read all at once
content = sys.stdin.read()
Rust equivalents:
use std::io::{self, BufRead};
// Line-by-line iteration
let stdin = io::stdin();
for line in stdin.lock().lines() {
let line = line?;
process(&line);
}
// Read all at once
use std::io::Read;
let mut content = String::new();
io::stdin().read_to_string(&mut content)?;
Example use case:
echo -e "Hello\nWorld" | python3 stream_processor.py stdin
→ 1: Hello
→ 2: World
→ Stats: 2 lines, 2 words
7. re Module - Regular Expressions
Python patterns needed:
import re
# Match at start
if re.match(r'^Hello', text):
print("Starts with Hello")
# Search anywhere
match = re.search(r'\d+', text)
if match:
print(f"Found number: {match.group()}")
# Find all
numbers = re.findall(r'\d+', text)
# Replace
result = re.sub(r'cat', 'dog', text)
# Compiled patterns
email_pattern = re.compile(r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')
if email_pattern.match(email):
print("Valid email")
# Case-insensitive
matches = re.findall(r'error', text, re.IGNORECASE)
Rust equivalents:
use regex::Regex;
// Match at start
if Regex::new(r"^Hello").unwrap().is_match(&text) {
println\!("Starts with Hello");
}
// Search anywhere
let re = Regex::new(r"\d+").unwrap();
if let Some(m) = re.find(&text) {
println\!("Found number: {}", m.as_str());
}
// Find all
let numbers: Vec<&str> = re.find_iter(&text).map(|m| m.as_str()).collect();
// Replace
let result = re.replace_all(&text, "dog");
// Compiled patterns
let email_pattern = Regex::new(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$").unwrap();
if email_pattern.is_match(&email) {
println\!("Valid email");
}
// Case-insensitive
use regex::RegexBuilder;
let re = RegexBuilder::new(r"error").case_insensitive(true).build().unwrap();
let matches: Vec<&str> = re.find_iter(&text).map(|m| m.as_str()).collect();
Example use case (examples/example_regex/pattern_matcher.py):
python3 pattern_matcher.py findall "[0-9]+" "I have 42 apples"
→ Found 2 matches: 42
python3 pattern_matcher.py email "user@example.com"
→ Valid email
Current errors:
error[E0423]: expected value, found crate 're'
re.IGNORECASE not recognized
re.match(), re.search(), re.findall() not transpiled
8. subprocess Module - Process Execution
Python patterns needed:
import subprocess
# Run command
result = subprocess.run(['ls', '-la'], capture_output=True, text=True)
print(result.stdout)
print(f"Exit code: {result.returncode}")
# With working directory
result = subprocess.run(['pwd'], cwd='/tmp', capture_output=True, text=True)
# Check for errors
result = subprocess.run(['false'], check=True) # Raises CalledProcessError
# Handle exceptions
try:
subprocess.run(['nonexistent'], check=True)
except subprocess.CalledProcessError as e:
print(f"Command failed: {e.returncode}")
except FileNotFoundError:
print("Command not found")
Rust equivalents:
use std::process::Command;
// Run command
let output = Command::new("ls")
.arg("-la")
.output()?;
let stdout = String::from_utf8(output.stdout)?;
println\!("{}", stdout);
println\!("Exit code: {:?}", output.status.code());
// With working directory
let output = Command::new("pwd")
.current_dir("/tmp")
.output()?;
// Check for errors
let status = Command::new("false").status()?;
if \!status.success() {
return Err("Command failed".into());
}
// Handle errors
match Command::new("nonexistent").status() {
Ok(status) if \!status.success() => {
println\!("Command failed: {:?}", status.code());
}
Err(e) if e.kind() == std::io::ErrorKind::NotFound => {
println\!("Command not found");
}
Err(e) => return Err(e.into()),
Ok(_) => {}
}
Example use case (examples/example_subprocess/task_runner.py):
python3 task_runner.py --capture echo "Hello, World\!"
→ Running: echo Hello, World\!
→ Exit code: 0
→ Output: Hello, World\!
Current errors:
error[E0425]: cannot find value 'subprocess' in this scope
- No transpilation for
subprocess.run()
9. tempfile Module - Temporary Files
Python patterns needed:
import tempfile
# Named temporary file
with tempfile.NamedTemporaryFile(mode='w', delete=False) as f:
temp_path = f.name
f.write(data)
# Temporary directory
with tempfile.TemporaryDirectory() as temp_dir:
work_file = os.path.join(temp_dir, 'work.txt')
Rust equivalents:
use tempfile::NamedTempFile;
use std::io::Write;
// Named temporary file
let mut temp_file = NamedTempFile::new()?;
let temp_path = temp_file.path().to_path_buf();
temp_file.write_all(data.as_bytes())?;
temp_file.persist(&temp_path)?; // Keep file after close
// Temporary directory
let temp_dir = tempfile::tempdir()?;
let work_file = temp_dir.path().join("work.txt");
// Directory deleted when temp_dir goes out of scope
Example use case:
python3 stream_processor.py temp --content "test data"
→ Created temporary file: /tmp/tmp_xyz.txt
→ File exists: 9 bytes
Priority 2 - MEDIUM: Advanced Features
10. Global Constants
Issue: Module-level dictionaries and constants not transpiled
Example (examples/example_config/config_manager.py):
DEFAULT_CONFIG = {
"database": {"host": "localhost", "port": 5432},
"logging": {"level": "INFO"},
}
def load_config(path):
if not Path(path).exists():
return DEFAULT_CONFIG.copy()
# ...
Error: cannot find value DEFAULT_CONFIG in this scope
Rust equivalent needed:
use once_cell::sync::Lazy;
use std::collections::HashMap;
static DEFAULT_CONFIG: Lazy<HashMap<String, serde_json::Value>> = Lazy::new(|| {
serde_json::json\!({
"database": {"host": "localhost", "port": 5432},
"logging": {"level": "INFO"}
}).as_object().unwrap().clone()
});
11. Subparser Variable Scoping
Issue: Subparser variables not tracked across scopes
Example:
subparsers = parser.add_subparsers(dest="action")
get_parser = subparsers.add_parser("get")
set_parser = subparsers.add_parser("set")
Error: cannot find value 'subparsers' in this scope
12. Optional Type Checking
Issue: if option: generates incorrect type check
Example:
if args.cwd: # args.cwd is Optional[str]
os.chdir(args.cwd)
Error: expected 'bool', found 'Option<String>'
Should generate:
if let Some(cwd) = &args.cwd {
std::env::set_current_dir(cwd)?;
}
// or
if args.cwd.is_some() {
std::env::set_current_dir(args.cwd.as_ref().unwrap())?;
}
Testing & Validation
All examples are fully functional in Python and ready for validation:
# Test environment example
cd examples/example_environment
python3 env_info.py system
# Test regex example
cd examples/example_regex
python3 pattern_matcher.py email "test@example.com"
# Test I/O streams example
cd examples/example_io_streams
echo "test" | python3 stream_processor.py stdin
Each example includes:
- ✅ Working Python implementation
- ✅ Comprehensive usage documentation
- ✅ README with Rust equivalents
- ✅ Clear error messages from depyler
Documentation
See project documentation for full details:
Recommended Implementation Order
Phase 1: Essential 3 (Unlocks ~70% of tools)
- os.environ - Environment variables
- os.path - Path operations
- Context managers - File safety
Phase 2: I/O & Text (Unlocks ~85% of tools)
- stdin iteration - Pipeline processing
- re module basics - Pattern matching
- subprocess.run() - Process execution
Phase 3: Advanced (Unlocks ~95% of tools)
- tempfile - Temporary files
- Optional type checking - Better ergonomics
- Global constants - Module-level data
- platform module - System introspection
Impact Summary
Current: 36.4% of CLI patterns supported
After Essential 3: ~70% supported
After Phase 2: ~85% supported
After Phase 3: ~95% supported
This would transform depyler from a proof-of-concept into a production-ready Python-to-Rust transpiler for CLI tools.
Related Issues
Repository: https://github.com/paiml/reprorusted-python-cli
Validation Framework: All examples with 100% I/O equivalence testing
Benchmarking: Scientific performance measurement ready when examples transpile
Summary
This feature request documents critical gaps in Python stdlib module support that prevent depyler from transpiling real-world CLI tools. Based on comprehensive testing with 11 examples, only 36.4% of common CLI patterns are currently supported.
The "Essential 3" features needed to unlock ~70% of real-world tools are:
withstatementCurrent Status
Depyler Compatibility: 4/11 examples (36.4%)
✅ What Works (4/11)
example_simple- Basic argparseexample_flags- Boolean flagsexample_positional- Positional argumentsexample_subcommands- Subcommands (FIXED in DEPYLER-0396!)❌ What Doesn't Work (7/11)
example_environmentexample_io_streamsexample_regexexample_subprocessexample_configexample_complexexample_stdlibPriority 0 - CRITICAL: os Module Support
Impact: Blocks 90%+ of real-world CLI tools
1. os.environ - Environment Variables
Python patterns needed:
Rust equivalents:
Example use case (
examples/example_environment/env_info.py):Current error:
Expression type not yet supported2. os.path - Path Operations
Python patterns needed:
Rust equivalents:
Example use case:
python3 env_info.py path ~/.bashrc → Exists: True → Is file: True python3 env_info.py join /home user config.json → Joined path: /home/user/config.jsonCurrent error:
Expression type not yet supported3. sys Module - System Information
Python patterns needed:
Rust equivalents:
Example use case:
4. platform Module - System Introspection
Python patterns needed:
Rust equivalents:
Priority 1 - HIGH: I/O and Text Processing
5. Context Managers -
withStatementPython patterns needed:
Rust equivalents (RAII handles cleanup automatically):
Example use case (
examples/example_io_streams/stream_processor.py):Current error:
Expression type not yet supported6. stdin Iteration
Python patterns needed:
Rust equivalents:
Example use case:
7. re Module - Regular Expressions
Python patterns needed:
Rust equivalents:
Example use case (
examples/example_regex/pattern_matcher.py):Current errors:
error[E0423]: expected value, found crate 're're.IGNORECASEnot recognizedre.match(),re.search(),re.findall()not transpiled8. subprocess Module - Process Execution
Python patterns needed:
Rust equivalents:
Example use case (
examples/example_subprocess/task_runner.py):Current errors:
error[E0425]: cannot find value 'subprocess' in this scopesubprocess.run()9. tempfile Module - Temporary Files
Python patterns needed:
Rust equivalents:
Example use case:
python3 stream_processor.py temp --content "test data" → Created temporary file: /tmp/tmp_xyz.txt → File exists: 9 bytesPriority 2 - MEDIUM: Advanced Features
10. Global Constants
Issue: Module-level dictionaries and constants not transpiled
Example (
examples/example_config/config_manager.py):Error:
cannot find value DEFAULT_CONFIG in this scopeRust equivalent needed:
11. Subparser Variable Scoping
Issue: Subparser variables not tracked across scopes
Example:
Error:
cannot find value 'subparsers' in this scope12. Optional Type Checking
Issue:
if option:generates incorrect type checkExample:
Error:
expected 'bool', found 'Option<String>'Should generate:
Testing & Validation
All examples are fully functional in Python and ready for validation:
Each example includes:
Documentation
See project documentation for full details:
examples/*/README.mdRecommended Implementation Order
Phase 1: Essential 3 (Unlocks ~70% of tools)
Phase 2: I/O & Text (Unlocks ~85% of tools)
Phase 3: Advanced (Unlocks ~95% of tools)
Impact Summary
Current: 36.4% of CLI patterns supported
After Essential 3: ~70% supported
After Phase 2: ~85% supported
After Phase 3: ~95% supported
This would transform depyler from a proof-of-concept into a production-ready Python-to-Rust transpiler for CLI tools.
Related Issues
Repository: https://github.com/paiml/reprorusted-python-cli
Validation Framework: All examples with 100% I/O equivalence testing
Benchmarking: Scientific performance measurement ready when examples transpile