A robust tool to transpile Python source code into V(vlang) code.
This guide provides information for developers who want to contribute to the Python to Vlang Transpiler.
# Clone the repository
git clone https://github.com/yaskhan/pythontovlang.git
cd pythontovlang
# Create virtual environment
python -m venv venv
source venv/bin/activate # Linux/macOS
# or
venv\Scripts\activate # Windows
# Install in development mode
pip install -e ".[dev]"
pythontovlang/
├── py2v_transpiler/
│ ├── __init__.py
│ ├── config.py # Configuration classes
│ ├── main.py # CLI entry point
│ ├── core/
│ │ ├── parser.py # AST parsing
│ │ ├── analyzer.py # Type inference
│ │ ├── generator.py # Code generation
│ │ ├── dependencies.py # Import analysis
│ │ ├── decorators.py # Decorator handling
│ │ ├── coroutines.py # Async support
│ │ └── translator/
│ │ ├── __init__.py # Main visitor
│ │ ├── base.py # Base class
│ │ ├── module.py # Module handling
│ │ ├── imports.py # Import translation
│ │ ├── expressions.py # Expressions
│ │ ├── literals.py # Literals
│ │ ├── variables.py # Variables
│ │ ├── control_flow.py # Control flow
│ │ ├── functions.py # Functions
│ │ └── classes.py # Classes
│ ├── stdlib_map/
│ │ ├── __init__.py
│ │ ├── mapper.py # Stdlib mappings
│ │ └── builtins.py # Built-in functions
│ ├── models/
│ │ ├── __init__.py
│ │ └── v_types.py # Type mappings
│ └── tests/
│ ├── test_*.py
│ └── translator/
├── docs/ # Documentation
├── examples/ # Example files
├── tests/ # Integration tests
├── setup.py # Package configuration
├── requirements.txt # Dependencies
├── README.md # Project overview
├── TODO.md # Feature checklist
└── AGENTS.md # Development guidelines
Edit the relevant module based on the feature or bug fix:
core/translator/stdlib_map/mapper.pymodels/v_types.pymain.pyWrite tests for your changes:
# tests/test_your_feature.py
def test_new_feature():
python_code = """
# Your Python code
"""
expected_v = """
// Expected V code
"""
assert transpile(python_code) == expected_v
# Run all tests
python -m pytest
# Run specific test file
python -m pytest tests/test_your_feature.py
# Run with verbose output
python -m pytest -v
# Run with coverage
python -m pytest --cov=py2v_transpiler
# Run mypy on the codebase
mypy py2v_transpiler/
# Test your changes on a sample file
py2v examples/sample.py
# Check the generated V code
cat examples/sample.v
# Try to compile with V
v run examples/sample.v
# Classes: PascalCase
class TypeInference:
pass
# Functions: snake_case
def map_python_type_to_v(py_type: str) -> str:
pass
# Constants: UPPER_CASE
MAX_RECURSION_DEPTH = 100
# Private methods: _prefix
def _internal_helper():
pass
Always use type hints:
from typing import Optional, List, Dict, Any
def process_node(
node: ast.AST,
context: Optional[Dict[str, Any]] = None
) -> List[str]:
pass
Step 1: Add AST visitor method
# core/translator/expressions.py
class ExpressionsMixin:
def visit_NewFeature(self, node: ast.NewFeature) -> str:
# Translate to V
return f"v_code_for({self.visit(node.child)})"
Step 2: Add type handling (if needed)
# models/v_types.py
def map_python_type_to_v(py_type: str) -> str:
if py_type == "NewType":
return "v_new_type"
Step 3: Add tests
# tests/translator/test_new_feature.py
def test_new_feature_basic():
code = """
x = new_feature(42)
"""
assert transpile(code) == "x := v_new_feature(42)"
Step 1: Add to mapper
# stdlib_map/mapper.py
class StdLibMapper:
def __init__(self):
self.mappings["new_module"] = {
"function": self._new_module_function,
}
def _new_module_function(self, args: List[str]) -> str:
return f"v_function({', '.join(args)})"
Step 2: Add tests
# tests/test_stdlib.py
def test_new_module_mapping():
code = """
from new_module import function
result = function(1, 2)
"""
assert "v_function(1, 2)" in transpile(code)
Step 1: Update type mapper
# models/v_types.py
def _map_ast_type(node: ast.AST, ...) -> str:
if isinstance(node, ast.NewTypeNode):
# Handle new type
return "v_type"
Step 2: Add tests
# tests/test_types.py
def test_new_type_mapping():
assert map_python_type_to_v("NewType[int]") == "v_type[int]"
from py2v_transpiler.core.parser import PyASTParser
parser = PyASTParser()
tree = parser.parse(source_code)
print(parser.dump_tree(tree)) # Debug AST
from py2v_transpiler.core.analyzer import TypeInference
analyzer = TypeInference()
analyzer.analyze(tree)
print(analyzer.get_type(some_node))
# Enable warnings for dynamic types
py2v script.py --warn-dynamic
Solution: Ensure code has type hints or add fallback handling:
def visit_Assign(self, node: ast.Assign) -> str:
inferred_type = self.type_inference.get_type(node.targets[0])
if inferred_type is None:
inferred_type = "Any" # Fallback
Solution: Check the generated V code for syntax errors:
# View generated code
cat script.v
# Try to compile
v build script.v
Solution: Add the mapping to stdlib_map/mapper.py or mark as unsupported.
import pytest
from py2v_transpiler.main import Transpiler
class TestFeature:
def test_basic_case(self):
"""Test the basic functionality."""
code = "..."
expected = "..."
assert Transpiler().transpile(code) == expected
def test_edge_case(self):
"""Test edge cases."""
pass
def test_error_case(self):
"""Test error handling."""
with pytest.raises(ExpectedError):
Transpiler().transpile(invalid_code)
When adding features, update:
# Good: Single pass
def visit_Module(self, node: ast.Module) -> str:
for stmt in node.body:
self.visit(stmt)
# Bad: Multiple walks
for stmt in node.body:
ast.walk(node) # Don't do this
# Good: List accumulation
output = []
for item in items:
output.append(self.visit(item))
return "\n".join(output)
# Bad: String concatenation
output = ""
for item in items:
output += self.visit(item) # Don't do this
setup.pyCHANGELOG.md (if exists)TODO.md# Tag the release
git tag -a v0.1.0 -m "Release v0.1.0"
git push origin v0.1.0
# Build package
python setup.py sdist bdist_wheel
# Upload to PyPI (when ready)
twine upload dist/*
Follow conventional commits:
feat: Add support for new Python feature
fix: Fix type inference for generics
docs: Update installation instructions
test: Add tests for stdlib mapping
refactor: Improve translator structure