Fortran to Python interface generator with derived type support for automated wrapper generation
—
Flexible code generation framework for producing both Fortran wrapper code and Python wrapper code with customizable formatting, structure, and output styles optimized for f2py compilation and Python integration.
Foundation class providing common code generation utilities and formatting capabilities.
class CodeGenerator(object):
"""Base code generation utility with formatting and output management."""
def __init__(self, indent, max_length, continuation, comment):
"""
Initialize code generator.
Parameters:
- indent: str, indentation string (spaces or tabs)
- max_length: int, maximum line length before wrapping
- continuation: str, line continuation character
- comment: str, comment prefix character
"""
def indent(self):
"""Increase current indentation level."""
def dedent(self):
"""Decrease current indentation level."""
def write(self, *args):
"""
Write arbitrary string arguments to the instance's code, split by
newline characters and implied newline after last arg.
"""
def writelines(self, items, insert=None, level=None):
"""
Write the given code lines to the instance's code.
Parameters:
- items: list of strings, code lines to be appended
- insert: int or None, insert lines after index instead of appending
- level: int or None, override current indent level
Returns:
int, index for next line to be added
"""
def split_long_lines(self):
"""Split long lines using continuation characters."""
def __str__(self):
"""Get generated code as formatted string."""Specialized generator for creating Fortran 90 wrapper code that interfaces with original Fortran code.
class F90WrapperGenerator(FortranVisitor, CodeGenerator):
"""Generate Fortran 90 wrapper code for f2py compilation."""The F90WrapperGenerator creates simplified Fortran interfaces that:
Specialized generator for creating high-level Python wrapper code that provides a Pythonic interface.
class PythonWrapperGenerator(FortranVisitor, CodeGenerator):
"""Generate Python wrapper code with object-oriented interface."""The PythonWrapperGenerator creates Python classes and functions that:
Utility functions supporting Python wrapper code generation.
def py_arg_value(arg):
"""Get Python argument value representation for wrapper functions."""
def normalise_class_name(name, name_map):
"""Normalize class names according to Python conventions."""
def format_call_signature(node):
"""Format procedure call signature for Python wrapper functions."""
def format_doc_string(node):
"""Format comprehensive docstrings from Fortran documentation."""from f90wrap.codegen import CodeGenerator
# Create generator with custom formatting
generator = CodeGenerator(indent=' ', max_length=80,
continuation='&', comment='!')
# Generate code with proper formatting
generator.write('subroutine example(x, y)')
generator.indent()
generator.write('real, intent(in) :: x')
generator.write('real, intent(out) :: y')
generator.write('y = x * 2.0')
generator.dedent()
generator.write('end subroutine example')
# Get formatted code
code = str(generator)
print(code)from f90wrap.f90wrapgen import F90WrapperGenerator
from f90wrap.fortran import walk_procedures
# Create F90 wrapper generator
f90_gen = F90WrapperGenerator(indent=' ', max_length=72,
continuation='&', comment='!')
# Generate wrappers for all procedures
for proc in walk_procedures(tree):
f90_gen.visit(proc)
# Write to file
with open('f90wrap_module.f90', 'w') as f:
f.write(str(f90_gen))from f90wrap.pywrapgen import PythonWrapperGenerator
from f90wrap.fortran import walk_modules
# Create Python wrapper generator
py_gen = PythonWrapperGenerator(indent=' ', max_length=80,
continuation='\\', comment='#')
# Generate Python classes for modules
for module in walk_modules(tree):
py_gen.visit(module)
# Write to file
with open('wrapper_module.py', 'w') as f:
f.write(str(py_gen))from f90wrap.codegen import CodeGenerator
from f90wrap.fortran import FortranVisitor
class CustomGenerator(FortranVisitor, CodeGenerator):
def __init__(self):
CodeGenerator.__init__(self, ' ', 80, '&', '!')
def visit_Subroutine(self, node):
self.write(f'! Wrapper for {node.name}')
self.write(f'subroutine wrap_{node.name}()')
self.indent()
# Custom wrapper logic
self.write('! Custom code here')
self.dedent()
self.write('end subroutine')
# Use custom generator
gen = CustomGenerator()
gen.visit(tree)
print(str(gen))Derived Type Handling:
Memory Management:
String Handling:
Exception Handling:
Object-Oriented Interface:
Argument Handling:
Documentation Generation:
Integration Features:
f90wrap_<module>.f90 # Main module wrapper
f90wrap_toplevel.f90 # Top-level procedure wrappers
f90wrap_types.f90 # Type-specific wrappers<module>.py # Main Python interface
<module>_types.py # Type definitions and classes
__init__.py # Package initializationGenerated Fortran wrappers are designed for seamless f2py compilation:
f2py -c -m _module f90wrap_*.f90 original_objects.oSupport for modern build systems through proper file organization:
# meson.build configuration
f2py_sources = ['f90wrap_module.f90', 'f90wrap_types.f90']Compatible with CMake-based Fortran projects:
# CMakeLists.txt configuration
set(F90WRAP_SOURCES f90wrap_module.f90 f90wrap_types.f90)Install with Tessl CLI
npx tessl i tessl/pypi-f90wrap