pglast.stream — The serialization machinery

class pglast.stream.OutputStream

A stream that has a concept of a pending separator between consecutive writes.

maybe_write_space(nextc=None, _special_chars={'"', '$', "'", '*', '+', '-', '/', '<', '=', '>', '@', '_'})

Emit a space when needed.

Parameters:

nextc – either None or the next character that will be written

Returns:

the number of characters written to the stream

If the last character written was neither a space nor an open parentheses, and nextc is either None or a special character, then emit a single whitespace.

separator()

Possibly insert a single whitespace character before next output.

When the last character written is not a space, set the pending_separator flag to True: the next call to write() will prepend a single whitespace to its argument if that begins with an alphanumeric character.

show(where=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>)

Emit current stream content, by default to stderr, to aid debugging.

swrite(s)

Shortcut for self.maybe_write_space(s[0]); self.write(s).

swrites(s)

Shortcut for self.swrite(s); self.separator().

write(s)

Emit string s.

Parameters:

s (str) – the string to emit

Returns:

the number of characters written to the stream

When s is not empty and pending_separator is True and the first character of s is alphanumeric, emit a single whitespace before writing out s and then reset pending_separator to False.

writes(s)

Shortcut for self.write(s); self.separator().

class pglast.stream.RawStream(separate_statements=1, special_functions=False, comma_at_eoln=False, semicolon_after_last_statement=False, comments=None, remove_pg_catalog_from_functions=False)

Basic SQL parse tree writer.

Parameters:
  • separate_statements (int) – 1 by default, tells how many empty lines should separate statements

  • special_functions (bool) – False by default, when True some functions are treated in a special way and emitted as equivalent constructs

  • comma_at_eoln (bool) – False by default, when True put the comma right after each item instead of at the beginning of the next item line

  • semicolon_after_last_statement (bool) – False by default, when True add a semicolon after the last statement, otherwise it is emitted only as a separator between multiple statements

  • comments – optional sequence of tuples with the comments extracted from the statement

  • remove_pg_catalog_from_functions (bool) – False by default, when True remove the pg_catalog schema from functions

This augments OutputStream and implements the basic machinery needed to serialize the parse tree produced by parse_sql() back to a textual representation, without any adornment.

__call__(sql, plpgsql=False)

Main entry point: execute print_node() on each statement in sql.

Parameters:
  • sql – the SQL statement

  • plpgsql (bool) – whether sql is really a plpgsql statement

Returns:

a string with the equivalent SQL obtained by serializing the syntax tree

The sql statement may be either a str containing the SQL in textual form, or a concrete ast.Node instance or a tuple of them.

This is the entry point to print a syntax tree: it first populates the ancestors slot of all the nodes in the tree (see visitors.populate_ancestors()), which the node printers rely upon.

dedent()

Do nothing, shall be overridden by the prettifier subclass.

expression(need_parens)

Create a context manager usable to conditionally wrap something within parentheses.

Parameters:

need_parens (bool) – whether to emit opening and closing parentheses

This is just the primitive to emit a literal ( … ) container, for example for the items of an IN list: deciding whether an expression operand needs parentheses is the job of print_operand().

get_printer_for_function(name, node=None)

Look for a specific printer for function name in SPECIAL_FUNCTIONS.

Parameters:

name (str) – the qualified name of the function

Returns:

either None or a callable

When the option special_functions is True, return the printer function associated with name, if present. For functions whose comma-call form is distinct from their SQL syntax form, also return the printer when the parsed node used SQL syntax.

indent(amount=0, relative=True)

Do nothing, shall be overridden by the prettifier subclass.

newline()

Emit a single whitespace, shall be overridden by the prettifier subclass.

print_b_expr(node)

Render node as a value that must be a valid b_expr.

Parameters:

node – an instance of Node

A b_expr is a restricted form of expression: when node is not one itself, it must be enclosed in parentheses and printed in an a_expr context, since the parenthesized form follows the wider a_expr grammar rules.

print_c_expr(node)

Render node as a value that must be a valid c_expr.

Parameters:

node – an instance of Node

A c_expr is the most restricted form of expression: only atomic nodes handled by a b_expr rule may appear in that position without parentheses, so when node is not one of those it must be enclosed in parentheses and printed in an a_expr context.

print_comment(comment)

Print the given comment, unconditionally in the C syntax, joining all lines.

Parameters:

comment – a Comment tuple containing the original comment

The comment style must change because the RawStream does not admit newlines, the whole statement is emitted in a single line of code, so SQL style comments are a no-no.

Warning

When the original style of comment was SQL, any occurrence of the string */ it contains is replaced with a visually equivalent but different *\N{ZERO WIDTH NO-BREAK SPACE}/, to avoid a premature end of the C style comment and thus a syntax error.

print_list(nodes, sep=',', relative_indent=None, standalone_items=None, are_names=False, is_symbol=False, item_needs_parens=None)

Execute print_node() on all the nodes, separating them with sep.

Parameters:
  • nodes – a sequence of Node instances

  • sep (str) – the separator between them

  • relative_indent (bool) – if given, the relative amount of indentation to apply before the first item, by default computed automatically from the length of the separator sep

  • standalone_items (bool) – whether a newline will be emitted before each item

  • are_names (bool) – whether the nodes are actually names, which possibly require to be enclosed between double-quotes

  • is_symbol (bool) – whether the nodes are actually a symbol such as an operator name, in which case the last one must be printed verbatim (e.g. "MySchema".===)

  • item_needs_parens – either None or a callable

print_lists(lists, sep=',', relative_indent=None, standalone_items=None, are_names=False, sublist_open='(', sublist_close=')', sublist_sep=',', sublist_relative_indent=None)

Execute print_list() on all the lists items.

Parameters:
  • lists – a sequence of sequences of Node instances

  • sep (str) – passed as is to print_list()

  • relative_indent (bool) – passed as is to print_list()

  • standalone_items (bool) – passed as is to print_list()

  • are_names (bool) – passed as is to print_list()

  • sublist_open (str) – the string that will be emitted before each sublist

  • sublist_close (str) – the string that will be emitted after each sublist

  • sublist_sep (str) – the separator between them each sublist

  • sublist_relative_indent (bool) – if given, the relative amount of indentation to apply before the first sublist, by default computed automatically from the length of the separator sublist_sep

print_name(nodes, sep='.')

Helper method, execute print_node() or print_list() as needed.

print_node(node, is_name=False, is_symbol=False)

Lookup the specific printer for the given node and execute it.

Parameters:
  • node – an instance of Node

  • is_name (bool) – whether this is a name of something, that may need to be double quoted

  • is_symbol (bool) – whether this is the name of an operator, should not be double quoted

Note

This method is meant to be called while printing a syntax tree, hence the ancestors slot of node is expected to have been populated for the whole tree by __call__() (via visitors.populate_ancestors()): a node printed on its own, out of a tree, has no ancestors and may raise AttributeError.

print_operand(node, parent_prec, side, ctx=None)

Render node as an operand of an expression with the given parent_prec.

Parameters:
  • node – an instance of Node

  • parent_prec (ExprPrec) – the precedence of the enclosing expression

  • side (Side) – either Side.LEFT or Side.RIGHT

  • ctx (ExprContext) – the context of the operand, by default the current expression context

This emits the wrapping parentheses iff the precedence and position rules require them, and then prints node in the appropriate context.

print_symbol(nodes, sep='.')

Helper method, execute print_node() or print_list() as needed.

push_expr_context(ctx)

Create a context manager setting the current expression context.

Parameters:

ctx (ExprContext) – the context this block of code prints into

The expression context tells which grammar rule the values printed within the block belong to, see pglast.precedence.

push_indent(amount=0, relative=True)

Create a no-op context manager, shall be overridden by the prettifier subclass.

show(where=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>)

Emit also current expression_level and a “pointer” showing current_column.

space(count=1, force=False)

Emit a single whitespace, shall be overridden by the prettifier subclass.

Parameters:
  • count (int) – ignored in this implementation

  • force (bool) – when True, unconditionally and immediately emit a single space

write_quoted_string(s)

Emit the string s as a single-quoted literal constant.

class pglast.stream.IndentedStream(compact_lists_margin=None, split_string_literals_threshold=None, **options)

Indented SQL parse tree writer.

Parameters:
  • compact_lists_margin (int) – an integer value that, if given, is used to print lists on a single line, when they do not exceed the given margin on the right

  • split_string_literals_threshold (int) – an integer value that, if given, is used as the threshold beyond that a string literal gets splitted in successive chunks of that length

  • **options – other options accepted by RawStream

This augments RawStream to emit a prettified representation of a parse tree.

dedent()

Pop the indentation level from the stack and set current_indent to that.

indent(amount=0, relative=True)

Push current indentation level to the stack, then set it adding amount to the current_column if relative is True otherwise to current_indent.

newline()

Emit a newline.

print_comment(comment)

Print the given comment, respecting the original style.

print_list(nodes, sep=',', relative_indent=None, standalone_items=None, are_names=False, is_symbol=False, item_needs_parens=None)

Execute print_node() on all the nodes, separating them with sep.

Parameters:
  • nodes – a sequence of Node instances

  • sep (str) – the separator between them

  • relative_indent (bool) – if given, the relative amount of indentation to apply before the first item, by default computed automatically from the length of the separator sep

  • standalone_items (bool) – whether a newline will be emitted before each item

  • are_names (bool) – whether the nodes are actually names, which possibly require to be enclosed between double-quotes

  • is_symbol (bool) – whether the nodes are actually an operator name, in which case the last one must be printed verbatim (such as "MySchema".===)

  • item_needs_parens – either None or a callable

push_indent(amount=0, relative=True)

Create a context manager that calls indent() and dedent() around a block of code.

This is just an helper to simplify code that adjusts the indentation level:

with output.push_indent(4):
    # code that emits something with the new indentation
show(where=<_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'>)

Emit also current_indent and indentation_stack.

space(count=1, force=False)

Emit consecutive spaces.

Parameters:
  • count (int) – how many spaces to emit

  • force (bool) – ignored by this implementation, honored only by RawStream.space()

write(s)

Write string s to the stream, adjusting the current_column accordingly.

Parameters:

s (str) – the string to emit

Returns:

the number of characters written to the stream

If s is a newline character (\n) set current_column to 0. Otherwise when current_column is 0 and current_indent is greater than 0 emit a number of whitespaces before emitting s, to indent it as expected.

write_quoted_string(s)

Emit the string s possibly splitted in successive chunks.

When the split_string_literals_threshold option is greater than 0 and the length of s exceeds that value, split the string into multiple chunks.