python-mod
A Rust procedural macro library for embedding Python code (Rython) directly into Rust projects. This crate allows you to write Python functions and have them compiled to Rust at build time, providing seamless integration between Python-like syntax and Rust performance.
Overview
Rython is a limited subset of Python that can be compiled to Rust. This crate provides procedural macros that:
- Parse Python source files at compile time
- Generate corresponding Rust code using the
python-ast
crate - Create Rust modules that can be used like native Rust code
- Support both single-file modules (
.py
) and package-style modules (__init__.py
)
Note: Rython is currently a very limited subset of Python. This will hopefully expand over time as the ecosystem develops.
Features
- ๐ Compile-time Python-to-Rust translation
- ๐ฆ Support for both single files and package modules
- ๐ ๏ธ Two macro variants:
python_module!
(with std) andpython_module_nostd!
(without std) - ๐ Rust code preamble support for importing native Rust dependencies
- โก Zero runtime overhead - everything happens at compile time
- ๐งช Comprehensive test suite with 23+ tests covering various scenarios
Installation
Add this to your Cargo.toml
:
[]
= "1.0.0"
Important: This crate requires nightly Rust due to the use of experimental procedural macro features.
Quick Start
1. Create a Python Module
Create a file src/math_ops.py
:
# Simple math operations
return +
return *
return
return +
# Constants
= 3.14159
2. Import the Module in Rust
In your src/main.rs
or src/lib.rs
:
use python_module;
// Import the Python module
python_module!;
3. Build and Run
Usage Examples
Basic Module Import
use python_module;
// Import a single Python file: src/utils.py
python_module!;
Package Module Import
For a package-style module, create src/my_package/__init__.py
:
return
return *
Then import it:
python_module!;
Module with Rust Preamble
python_module!
Module Without Standard Library
use python_module_nostd;
// Import without including standard Python libraries
python_module_nostd!;
Supported Python Features
Currently, Rython supports a limited subset of Python syntax:
โ Supported
- Function definitions (
def
) - Return statements
- Basic arithmetic operations (
+
,-
,*
,/
) - Variable assignments
- Constants
- Basic control flow (
if
,else
) - Recursive functions
- String operations
- Integer and float literals
โ ๏ธ Limited/Experimental
- List operations
- Dictionary operations
- Loop constructs
โ Not Yet Supported
- Classes and objects
- Imports
- Exception handling
- Advanced Python features
- Most of the Python standard library
File Structure
The macro looks for Python files in the following locations:
- Single file module:
src/{module_name}.py
- Package module:
src/{module_name}/__init__.py
Example project structure:
my_project/
โโโ Cargo.toml
โโโ src/
โ โโโ lib.rs
โ โโโ math_utils.py # Single file module
โ โโโ string_ops.py # Another single file module
โ โโโ advanced/ # Package module
โ โโโ __init__.py
Usage:
python_module!; // Imports src/math_utils.py
python_module!; // Imports src/string_ops.py
python_module!; // Imports src/advanced/__init__.py
API Reference
python_module!(module_name)
Imports a Python module with standard library support.
Parameters:
module_name
: The name of the Python module to import
Example:
python_module!;
python_module_nostd!(module_name)
Imports a Python module without standard library support.
Parameters:
module_name
: The name of the Python module to import
Example:
python_module_nostd!;
python_module!{module_name /* Rust preamble */}
Imports a Python module with custom Rust code preamble.
Parameters:
module_name
: The name of the Python module to import- Rust code block: Code to include at the top of the generated module
Example:
python_module!
Development
Building
Testing
The crate includes a comprehensive test suite with 23+ tests:
# Run all tests
# Run specific test categories
Contributing
- Ensure you're using nightly Rust
- Run the full test suite:
cargo test
- Add tests for new functionality
- Update documentation as needed
Architecture
The crate works by:
- Parse-time: The procedural macro reads Python source files
- AST Generation: Uses
python-ast
to parse Python into a Rust AST - Code Generation: Converts the Python AST to Rust
TokenStream
- Module Creation: Wraps generated code in a Rust module
Python Source โ python-ast โ Rust AST โ TokenStream โ Rust Module
Limitations
- Nightly Rust Required: Uses experimental proc-macro features
- Limited Python Subset: Only basic Python constructs are supported
- Compile-time Only: Python code is translated at build time, not runtime
- No Python Runtime: Generated code is pure Rust, no Python interpreter needed
Roadmap
Future improvements may include:
- Expanded Python syntax support
- Better error messages and debugging
- Support for Python classes
- Integration with more Python constructs
- Performance optimizations
- Better tooling and IDE support
License
Licensed under the Apache License, Version 2.0. See LICENSE for details.
Dependencies
quote
- For Rust code generationproc-macro2
- Advanced procedural macro functionalityproc-macro-error
- Better error handling in macrospython-ast
- Python AST parsing and Rust code generationpath_macro
- Path manipulation utilities
Related Projects
- PyO3 - Python bindings for Rust
- python-ast - Python AST parsing for Rust
- Rython - The Python subset compiler
Note: This project is in active development. The Python subset supported by Rython is currently limited, but is expected to grow over time. Contributions and feedback are welcome!