in bowler/query.py [0:0]
def encapsulate(self, internal_name: str = "") -> "Query":
transform = self.current
if transform.selector not in ("attribute"):
raise ValueError("encapsulate requires select_attribute")
if not any("filter_in_class" in f.__name__ for f in transform.filters):
raise ValueError("encapsulate requires in_class filter")
make_property = Once()
old_name = transform.kwargs["name"]
new_name = internal_name or f"_{old_name}"
if new_name.startswith("__"):
raise ValueError(
"renaming {old_name} -> {new_name} is dangerous, "
"please specify internal_name to avoid name mangling"
)
def encapsulate_transform(
node: LN, capture: Capture, filename: Filename
) -> None:
if "attr_assignment" in capture:
leaf = capture["attr_name"]
leaf.replace(Name(new_name, prefix=leaf.prefix))
if make_property:
# TODO: capture and use type annotation from original assignment
class_node = get_class(node)
suite = find_first(class_node, SYMBOL.suite)
assert isinstance(suite, Node)
indent_node = find_first(suite, TOKEN.INDENT)
assert isinstance(indent_node, Leaf)
indent = indent_node.value
getter = Node(
SYMBOL.decorated,
[
Node(
SYMBOL.decorator,
[
Leaf(TOKEN.INDENT, indent),
Leaf(TOKEN.AT, "@"),
Name("property"),
Leaf(TOKEN.NEWLINE, "\n"),
],
),
Node(
SYMBOL.funcdef,
[
Name("def", indent),
Name(old_name, prefix=" "),
Node(
SYMBOL.parameters,
[LParen(), Name("self"), RParen()],
),
Leaf(TOKEN.COLON, ":"),
Node(
SYMBOL.suite,
[
Newline(),
Leaf(TOKEN.INDENT, indent + " "),
Node(
SYMBOL.simple_stmt,
[
Node(
SYMBOL.return_stmt,
[
Name("return"),
Node(
SYMBOL.power,
Attr(
Name("self"),
Name(new_name),
),
prefix=" ",
),
],
),
Newline(),
],
),
Leaf(TOKEN.DEDENT, "\n" + indent),
],
),
],
prefix=indent,
),
],
)
setter = Node(
SYMBOL.decorated,
[
Node(
SYMBOL.decorator,
[
Leaf(TOKEN.AT, "@"),
Node(
SYMBOL.dotted_name,
[Name(old_name), Dot(), Name("setter")],
),
Leaf(TOKEN.NEWLINE, "\n"),
],
),
Node(
SYMBOL.funcdef,
[
Name("def", indent),
Name(old_name, prefix=" "),
Node(
SYMBOL.parameters,
[
LParen(),
Node(
SYMBOL.typedargslist,
[
Name("self"),
Comma(),
Name("value", prefix=" "),
],
),
RParen(),
],
),
Leaf(TOKEN.COLON, ":"),
Node(
SYMBOL.suite,
[
Newline(),
Leaf(TOKEN.INDENT, indent + " "),
Node(
SYMBOL.simple_stmt,
[
Node(
SYMBOL.expr_stmt,
[
Node(
SYMBOL.power,
Attr(
Name("self"),
Name(new_name),
),
),
Leaf(
TOKEN.EQUAL,
"=",
prefix=" ",
),
Name("value", prefix=" "),
],
),
Newline(),
],
),
Leaf(TOKEN.DEDENT, "\n" + indent),
],
),
],
prefix=indent,
),
],
)
suite.insert_child(-1, getter)
suite.insert_child(-1, setter)
prev = find_previous(getter, TOKEN.DEDENT, recursive=True)
curr = find_last(setter, TOKEN.DEDENT, recursive=True)
if prev and curr:
assert isinstance(prev, Leaf) and isinstance(curr, Leaf)
prev.prefix, curr.prefix = curr.prefix, prev.prefix
prev.value, curr.value = curr.value, prev.value
transform.callbacks.append(encapsulate_transform)
return self