Skip to content

Commit

Permalink
enable writing module code directly to file
Browse files Browse the repository at this point in the history
  • Loading branch information
asvarga-sedaro committed Jul 18, 2024
1 parent 72701e4 commit 8767302
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
25 changes: 25 additions & 0 deletions libcst/_nodes/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# LICENSE file in the root directory of this source tree.


import io
from contextlib import contextmanager
from dataclasses import dataclass, field
from typing import Iterable, Iterator, List, Optional, Sequence, TYPE_CHECKING, Union
Expand Down Expand Up @@ -70,6 +71,30 @@ def record_syntactic_position(
yield


@add_slots
@dataclass(frozen=False)
class CodegenWriter(CodegenState):
"""
A CodegenState that writes to a file-like object.
"""

writer: io.TextIOBase = None # need a default value for dataclass

def __post_init__(self) -> None:
if self.writer is None:
raise TypeError("writer must be provided")

Check warning on line 85 in libcst/_nodes/internal.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/internal.py#L84-L85

Added lines #L84 - L85 were not covered by tests

def add_indent_tokens(self) -> None:
for token in self.indent_tokens:
self.writer.write(token)

Check warning on line 89 in libcst/_nodes/internal.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/internal.py#L88-L89

Added lines #L88 - L89 were not covered by tests

def add_token(self, value: str) -> None:
self.writer.write(value)

Check warning on line 92 in libcst/_nodes/internal.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/internal.py#L92

Added line #L92 was not covered by tests

def pop_trailing_newline(self) -> None:
pass

Check warning on line 95 in libcst/_nodes/internal.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/internal.py#L95

Added line #L95 was not covered by tests


def visit_required(
parent: "CSTNode", fieldname: str, node: CSTNodeT, visitor: "CSTVisitorT"
) -> CSTNodeT:
Expand Down
26 changes: 25 additions & 1 deletion libcst/_nodes/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
# This source code is licensed under the MIT license found in the
# LICENSE file in the root directory of this source tree.

import io
from dataclasses import dataclass
from typing import cast, Optional, Sequence, TYPE_CHECKING, TypeVar, Union

from libcst._add_slots import add_slots
from libcst._nodes.base import CSTNode
from libcst._nodes.internal import CodegenState, visit_body_sequence, visit_sequence
from libcst._nodes.internal import (
CodegenState,
CodegenWriter,
visit_body_sequence,
visit_sequence,
)
from libcst._nodes.statement import (
BaseCompoundStatement,
get_docstring_impl,
Expand Down Expand Up @@ -136,6 +142,24 @@ def code_for_node(self, node: CSTNode) -> str:
node._codegen(state)
return "".join(state.tokens)

def write_code(self, writer: io.TextIOBase):
"""
Like :meth:`code`, but writes the code to the given file-like object.
"""
self.write_code_for_node(self, writer)

Check warning on line 149 in libcst/_nodes/module.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/module.py#L149

Added line #L149 was not covered by tests

def write_code_for_node(self, node: CSTNode, writer: io.TextIOBase):
"""
Like :meth:`code_for_node`, but writes the code to the given file-like object.
"""

state = CodegenWriter(

Check warning on line 156 in libcst/_nodes/module.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/module.py#L156

Added line #L156 was not covered by tests
default_indent=self.default_indent,
default_newline=self.default_newline,
writer=writer,
)
node._codegen(state)

Check warning on line 161 in libcst/_nodes/module.py

View check run for this annotation

Codecov / codecov/patch

libcst/_nodes/module.py#L161

Added line #L161 was not covered by tests

@property
def config_for_parsing(self) -> "PartialParserConfig":
"""
Expand Down

0 comments on commit 8767302

Please sign in to comment.