Skip to content

Scaffolding API Reference

The headerkit.scaffold module provides domain models and the execution engine for project layouts, standard-library templates, and custom BYOScaffolder plugins.


Classes

OutputFile dataclass

OutputFile(path, content, is_executable=False, preserve_existing=False)

A single file to be written in a project layout.

ProjectLayout dataclass

ProjectLayout(files=list())

A collection of output files comprising a project or package layout.

get_file

get_file(path)

Find an output file by its relative project path.

Source code in headerkit/scaffold.py
def get_file(self, path: str) -> OutputFile | None:
    """Find an output file by its relative project path."""
    for f in self.files:
        if f.path == path:
            return f
    return None

write_to_disk

write_to_disk(target_dir, *, overwrite=True)

Write all files in this layout to the destination directory.

Source code in headerkit/scaffold.py
def write_to_disk(self, target_dir: Path | str, *, overwrite: bool = True) -> list[Path]:
    """Write all files in this layout to the destination directory."""
    written: list[Path] = []
    base = Path(target_dir).resolve()
    for f in self.files:
        p = (base / f.path).resolve()
        if not p.is_relative_to(base):
            raise ValueError(f"Path traversal detected: {f.path}")
        p.parent.mkdir(parents=True, exist_ok=True)
        if p.exists() and (f.preserve_existing or not overwrite):
            continue
        p.write_text(f.content, encoding="utf-8")
        if f.is_executable:
            p.chmod(p.stat().st_mode | 0o111)
        written.append(p)
    return written

ScaffoldOptions dataclass

ScaffoldOptions(package_name='bindings', target_language='nim', layout='file', options=dict(), interactive=False, extra_context=dict(), test_type='both', test_runner='tripwire')

Configuration options for project scaffolding.

get_option

get_option(name, default=None)

Get a writer-specific option value.

Source code in headerkit/scaffold.py
def get_option(self, name: str, default: Any = None) -> Any:
    """Get a writer-specific option value."""
    if name in self.options:
        return self.options[name]
    if hasattr(self, name):
        return getattr(self, name)
    return default

BYOScaffolder

Protocol and base class for Bring-Your-Own-Scaffolder plugins.

scaffold

scaffold(unit, options)

Generate a ProjectLayout for the given SourceUnit and options.

Source code in headerkit/scaffold.py
def scaffold(self, unit: SourceUnit | Header, options: ScaffoldOptions) -> ProjectLayout:
    """Generate a ProjectLayout for the given SourceUnit and options."""
    raise NotImplementedError

StdlibScaffolder

Bases: BYOScaffolder

Zero-dependency standard library project scaffolder.

scaffold

scaffold(unit, options)

Generate project layout using built-in templates.

Source code in headerkit/scaffold.py
def scaffold(self, unit: SourceUnit | Header, options: ScaffoldOptions) -> ProjectLayout:
    """Generate project layout using built-in templates."""
    from headerkit.writers import get_writer

    writer_target = self._resolve_target(options.target_language)
    writer = get_writer(writer_target)
    if hasattr(writer, "write_layout"):
        return writer.write_layout(unit, options)

    return self._scaffold_single_file(unit, options, writer_target)

Functions

scaffold

scaffold(unit, options, context=None)

Scaffold a project layout for a source unit, dispatching to registered hooks.

Source code in headerkit/scaffold.py
def scaffold(
    unit: SourceUnit | Header,
    options: ScaffoldOptions,
    context: Any = None,
) -> ProjectLayout:
    """Scaffold a project layout for a source unit, dispatching to registered hooks."""
    from headerkit.hooks import PipelineContext

    if context is None:
        ctx = PipelineContext(
            writer=options.target_language,
            target=options.target_language,
            layout=options.layout,
            options=options.options,
        )
    else:
        if getattr(context, "layout", None) is None:
            ctx = PipelineContext(
                backend=getattr(context, "backend", None),
                writer=getattr(context, "writer", None) or options.target_language,
                target=getattr(context, "target", None) or options.target_language,
                layout=options.layout,
                language=getattr(context, "language", None),
                classification=getattr(context, "classification", None),
                runtime=getattr(context, "runtime", None),
                options=getattr(context, "options", None) or options.options,
            )
        else:
            ctx = context

    dispatcher = HookDispatcher()
    unit = dispatcher.waterfall("transform_unit", unit, context=ctx)
    result = dispatcher.first_result("scaffold_project", unit, options, context=ctx)
    if isinstance(result, ProjectLayout):
        return result
    return StdlibScaffolder().scaffold(unit, options)

prompt_scaffold_options

prompt_scaffold_options(defaults=None, *, is_tty=None)

TTY-aware interactive prompt wizard for scaffolding options.

Source code in headerkit/scaffold.py
def prompt_scaffold_options(
    defaults: ScaffoldOptions | None = None,
    *,
    is_tty: bool | None = None,
) -> ScaffoldOptions:
    """TTY-aware interactive prompt wizard for scaffolding options."""
    opts = defaults if defaults is not None else ScaffoldOptions()
    tty_active = is_tty if is_tty is not None else (sys.stdin.isatty() and sys.stdout.isatty())

    if not tty_active:
        return opts

    try:
        raw_pkg = input(f"Package name [{opts.package_name}]: ").strip()
        pkg_name = raw_pkg or opts.package_name

        raw_lang = input(f"Target language (nim, mojo, ctypes, cffi) [{opts.target_language}]: ").strip()
        target_lang = raw_lang or opts.target_language

        raw_layout = input(f"Layout (file, package) [{opts.layout}]: ").strip()
        layout = raw_layout or opts.layout

        raw_test = input(f"Test generation (both, tripwire, unit, none) [{opts.test_type}]: ").strip()
        test_type = raw_test or opts.test_type

        return ScaffoldOptions(
            package_name=pkg_name,
            target_language=target_lang,
            layout=layout,
            options=dict(opts.options),
            test_type=test_type,
            test_runner=opts.test_runner,
            interactive=True,
            extra_context=opts.extra_context,
        )
    except (EOFError, KeyboardInterrupt):
        return opts