simvx.core.scene_io.source._source_ast.document

The seam over CPython’s own parser: text in, spliced text out.

The document’s only state is the author’s text. Every mutation computes a splice, applies it, and re-runs ast.parse and one tokenize pass over the result, so after any operation the document is by construction a parseable file whose text is what :meth:AstDocument.dump returns. There is no tree to keep in step and no invariant a splice has to hand-repair, which is the whole reason this backend is shorter than the one it replaces.

The splice is applied to a copy and the copy is parsed before anything is committed, so an edit that would leave the file unreadable leaves the document exactly as it was.

Handles are markers rather than nodes. A :class:AstStatement holds an anchor offset – where its statement starts – and every splice remaps the live anchors through the parts of the text it kept. A statement the splice wrote over is a statement no anchor survives, so a handle to it says

class:

~simvx.core.scene_io.source.StaleHandleError at the point of use rather than answering from something the document no longer holds. Handles are interned per anchor, which is what makes two handles to one statement the same handle.

Module Contents

Classes

AstDocument

A document whose whole state is the text it dumps.

AstStatement

A marker into a document, resolved against its statement table on every use.

AstImportDecl

One import or from ... import ... line.

AstClassDecl

One top-level class, and the two blocks a scene is edited through.

Functions

parse_document

Parse text, presenting CPython’s own refusal when it will not parse.

parse_one_expression

Raise :class:SceneSyntaxError unless text is one whole expression.

Data

API

simvx.core.scene_io.source._source_ast.document.__all__

[‘AstDocument’, ‘parse_document’, ‘parse_one_expression’]

class simvx.core.scene_io.source._source_ast.document.AstDocument(state: simvx.core.scene_io.source._source_ast.document._State)[source]

Bases: simvx.core.scene_io.source.SourceDocument

A document whose whole state is the text it dumps.

Initialization

__slots__

(‘_state’, ‘_original’, ‘_epoch’, ‘_handles’)

property backend_name: str[source]
property epoch: int[source]
property original_text: str[source]
dump() str[source]
is_unchanged() bool[source]
top_level_classes() list[simvx.core.scene_io.source.ClassDecl][source]
find_class(name: str) simvx.core.scene_io.source.ClassDecl | None[source]
imports() list[simvx.core.scene_io.source.ImportDecl][source]
top_level_statements() list[simvx.core.scene_io.source.Statement][source]
insert_top_level(text: str, *, after: simvx.core.scene_io.source.Statement | None = None) simvx.core.scene_io.source.Statement[source]
ensure_import(name: str, *, from_: str | None = None) None[source]
remove_import(name: str, *, from_: str | None = None) None[source]
classmethod parse(text: str, *, backend: str | None = None) simvx.core.scene_io.source.SourceDocument
class simvx.core.scene_io.source._source_ast.document.AstStatement(document: simvx.core.scene_io.source._source_ast.document.AstDocument, anchor: int)[source]

Bases: simvx.core.scene_io.source.Statement

A marker into a document, resolved against its statement table on every use.

Initialization

__slots__

(‘_document’, ‘_anchor’, ‘_alive’)

__repr__() str[source]
text() str[source]
kind() simvx.core.scene_io.source.StatementKind[source]
leading_trivia() str[source]
trailing_comment() str | None[source]
shares_line() bool[source]
line_group() list[simvx.core.scene_io.source.Statement][source]
line() int[source]
column() int[source]
is_live() bool[source]
call() simvx.core.scene_io.source._source_ast.calls.AstCallView | None[source]
set_value(text: str) None[source]
bound_names() set[str][source]
mentioned_names() set[str][source]
rename_local(old: str, new: str) int[source]
class simvx.core.scene_io.source._source_ast.document.AstImportDecl(document: simvx.core.scene_io.source._source_ast.document.AstDocument, statement: simvx.core.scene_io.source._source_ast.document.AstStatement)[source]

Bases: simvx.core.scene_io.source.ImportDecl

One import or from ... import ... line.

Initialization

__slots__

(‘_document’, ‘_statement’)

property statement: simvx.core.scene_io.source.Statement[source]
property module: str | None[source]
property names: list[simvx.core.scene_io.source.ImportedName][source]
class simvx.core.scene_io.source._source_ast.document.AstClassDecl(document: simvx.core.scene_io.source._source_ast.document.AstDocument, statement: simvx.core.scene_io.source._source_ast.document.AstStatement)[source]

Bases: simvx.core.scene_io.source.ClassDecl

One top-level class, and the two blocks a scene is edited through.

Initialization

__slots__

(‘_document’, ‘_statement’)

property name: str[source]
property statement: simvx.core.scene_io.source.Statement[source]
line() int[source]
body_statements() list[simvx.core.scene_io.source.Statement][source]
has_init() bool[source]
init_statements() list[simvx.core.scene_io.source.Statement][source]
bases() list[str][source]
set_base(old: str, new: str) None[source]
insert(text: str, *, after: simvx.core.scene_io.source.Statement | simvx.core.scene_io.source.Anchor) simvx.core.scene_io.source.Statement[source]
insert_before(text: str, *, before: simvx.core.scene_io.source.Statement) simvx.core.scene_io.source.Statement[source]
remove(stmt: simvx.core.scene_io.source.Statement) None[source]
reorder(groups: list[list[simvx.core.scene_io.source.Statement]]) None[source]
simvx.core.scene_io.source._source_ast.document.parse_document(text: str) simvx.core.scene_io.source._source_ast.document.AstDocument[source]

Parse text, presenting CPython’s own refusal when it will not parse.

simvx.core.scene_io.source._source_ast.document.parse_one_expression(text: str) None[source]

Raise :class:SceneSyntaxError unless text is one whole expression.