Source code for ifgen.generation.python

"""
A module implementing code-generation interfaces for Python.
"""

# built-in
from contextlib import contextmanager
from typing import Iterable, Iterator

# third-party
from vcorelib.io import IndentedFileWriter

PythonImports = dict[str, list[str]]


[docs] def write_imports( writer: IndentedFileWriter, label: str, imports: PythonImports, ) -> None: """Write a group of Python imports to a file.""" writer.empty() writer.write(f"# {label}") for key, values in sorted(imports.items()): writer.write(f"from {key} import {', '.join(values)}")
[docs] def python_imports( writer: IndentedFileWriter, built_in: PythonImports = None, third_party: PythonImports = None, internal: PythonImports = None, final_empty: int = 2, ) -> None: """Write Python-module imports.""" if built_in: write_imports(writer, "built-in", built_in) if third_party: write_imports(writer, "third-party", third_party) if internal: write_imports(writer, "internal", internal) writer.empty(count=final_empty)
[docs] def python_docstring( writer: IndentedFileWriter, *docstrings: str, empty: bool = True ) -> None: """Write docstring data.""" writer.write('"""') for docstring in docstrings: writer.write(docstring) writer.write('"""') if empty: writer.empty()
[docs] @contextmanager def python_class( writer: IndentedFileWriter, name: str, docstring: str, parents: list[str] = None, final_empty: int = 2, ) -> Iterator[None]: """Write class definition contents.""" line = f"class {name}" if parents: line += f"({', '.join(parents)})" line += ":" writer.write(line) with writer.indented(): python_docstring(writer, docstring) yield writer.empty(count=final_empty)
[docs] @contextmanager def python_function( writer: IndentedFileWriter, name: str, docstring: str, params: str = "", return_type: str = "None", final_empty: int = 2, decorators: Iterable[str] = None, ) -> Iterator[None]: """Write a Python function.""" if decorators: for decorator in decorators: writer.write("@" + decorator) writer.write(f"def {name}({params}) -> {return_type}:") with writer.indented(): python_docstring(writer, docstring) yield writer.empty(count=final_empty)