Section

All snippets and generators are provided an section, which they must use to generate their output.

The section provides a convenient if simple abstraction for output generation. The main objective of the API is to control lines and indentation. This permits gcgen to ensure that output generated from a snippet is always properly indented, such that each line of the snippet are indented relative to the indentation of the snippet start line.

Example

from gcgen.api import Scope, Section, Json, snippet

@snippet("my-snippet")
def include_file_output(sec: Section, scope: Scope, val: Json):
    if isinstance(v, str):
        filename = v
    else:
        raise RuntimeError("expected filename passed as string argument")
    sec.emitln(f"""with open({filename!r}) as fh:""")
    sec.indent()
    sec.emitln("for lines in fh.readlines():")
    sec.indent()
    sec.emitln("...")

Given the following file:

myfile.py
def some_function():
    # <<? include_file_output "/etc/issue" ?>>
    # <<? /include_file_output ?>>

The expanded output would become:

myfile.py
def some_function():
    # <<? include_file_output "/etc/issue" ?>>
    with open("/etc/issue") as fh:
        for lines in fh.readlines()
            ...
    # <<? /include_file_output ?>>

Note: While the section controls the level of indentation, the characters used to indent the line is actually determined by gcgen_indent_by, which can be used to define how indentation should be handled on a file-type basis.

Section API

class gcgen.api.Section

A class for storing (buffered) text/code output.

A section is an abstraction of text writing which provides 2 capabilities: 1. It provides a way to control indentation 2. It provides a way to nest Section(s) within a Section

(1) The indentation abstraction facilitates composition and reuse of generator code, because each helper function only needs to call indent()/ dedent() to adjust line indentation, rather than embedding a fixed, absolute amount of indentation into the strings of each line written out.

(2) By allowing a section to contain other sections, it becomes possible to define ‘placeholders’ which can be filled out at a later time. Effectively making it possible to define the final output out of order, e.g. adding more variable definitions to the start of a function as it becomes necessary.

add_section(s: Section) Section

Add section to be filled in when desired.

Adds provided section object such that its contents will be preceded by the current contents of this section and superceded by any subsequently added contents to this section.

dedent() Section

Dedent lines by one.

Causes all future lines to be indented one level less.

Note: this function will cause a newline if the current line has any contents already written to it (using emit).

emit(*elems: str) Section

Emit one or more string elements.

emitln(*elems: str) Section

Emit one or more string elements followed by a newline.

emitln_l(*elems: str) Section

Emit line, then dedent.

NOTE: deprecated, use sec.emitln(…).dedent() instead.

emitln_r(*elems: str) Section

Write line, then indent.

NOTE: deprecated, use sec.emitln(…).indent() instead

ensure_padding_lines(nlines: int) Section

Ensure (at least) n empty lines of padding between two sections

NOTE: if this is the top-level buffer and it is empty, this becomes a NO-OP

fl() Section

emit newline iff. not currently at the beginning of a line.

freshline() Section

emit newline iff. not currently at the beginning of a line.

indent() Section

Indent subsequent lines.

Causes all future lines to be indented one level more.

Note: this function will cause a newline if the current line has any contents already written to it (using emit).

newline() Section

add a newline.