Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre compute static attributes #81

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Changelog
- fix: inconsistencies when inserting lines around code blocks
- inserting a blank lines inserts effectively a \n in a LineProxyList
- new helper methods: .next_recursive and .previous_recursive https://redbaron.readthedocs.org/en/latest/other.html
- performance improvement: pre-compute ._render and ._identifiers attributes

0.5.1 (2015-03-11)
------------------
Expand Down
60 changes: 27 additions & 33 deletions redbaron.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,14 @@ def get_holder_on_attribute(class_, node):
return pos

if isinstance(node, NodeList):
return next((key for (_, key, _) in parent._render() if getattr(parent, key) is node or getattr(getattr(parent, key), "node_list", None) is node), None)
for (_, key, _) in parent._render:
child = parent.find(key, recursive=False)
if child is node \
or getattr(child, "node_list", None) is node:
return key

to_return = next((key for (_, key, _) in parent._render() if key == node.on_attribute), None)

to_return = next((key for (_, key, _) in parent._render if key == node.on_attribute), None)
return to_return


Expand Down Expand Up @@ -271,7 +276,7 @@ def _iter_in_rendering_order(self, node):
return
if not (isinstance(node, Node) and node.type == "endl"):
yield node
for kind, key, display in node._render():
for kind, key, display in node._render:
if kind == "constant":
yield node
elif kind == "string":
Expand Down Expand Up @@ -465,7 +470,9 @@ def __init__(self, node, parent=None, on_attribute=None):
self._list_keys = []
self._dict_keys = []
self.type = node["type"]
for kind, key, _ in filter(lambda x: x[0] != "constant", self._render()):
self._render = nodes_rendering_order[self.type]

for kind, key, _ in filter(lambda x: x[0] != "constant", self._render):
if kind == "key":
if node[key]:
setattr(self, key, Node.from_fst(node[key], parent=self, on_attribute=key))
Expand All @@ -486,6 +493,14 @@ def __init__(self, node, parent=None, on_attribute=None):

self.init = False

self._identifiers = [x.lower() for x in [
self.type,
self.__class__.__name__,
self.__class__.__name__.replace("Node", ""),
self.type + "_"
] + self._other_identifiers]


@classmethod
def from_fst(klass, node, parent=None, on_attribute=None):
class_name = "".join(map(lambda x: x.capitalize(), node["type"].split("_"))) + "Node"
Expand Down Expand Up @@ -627,13 +642,8 @@ def _get_list_attribute_is_member_off(self):

return in_list


def find(self, identifier, *args, **kwargs):
if "recursive" in kwargs:
recursive = kwargs["recursive"]
kwargs = kwargs.copy()
del kwargs["recursive"]
else:
def find(self, identifier, *args, recursive=None, **kwargs):
if recursive is None:
recursive = True

if self._node_match_query(self, identifier, *args, **kwargs):
Expand All @@ -642,26 +652,22 @@ def find(self, identifier, *args, **kwargs):
if not recursive:
return None

for kind, key, _ in filter(lambda x: x[0] in ("list", "key"), self._render()):
for kind, key, _ in filter(lambda x: x[0] in ("list", "key"), self._render):
if kind == "key":
i = getattr(self, key)
if not i:
continue

found = i.find(identifier, *args, **kwargs)
found = i.find(identifier, *args, recursive=recursive, **kwargs)
if found:
return found

elif kind == "list":
attr = getattr(self, key).node_list if isinstance(getattr(self, key), ProxyList) else getattr(self, key)
for i in attr:
found = i.find(identifier, *args, **kwargs)
found = i.find(identifier, *args, recursive=recursive, **kwargs)
if found:
return found

else:
raise Exception()

def __getattr__(self, key):
if key.endswith("_") and key[:-1] in self._dict_keys + self._list_keys + self._str_keys:
return getattr(self, key[:-1])
Expand Down Expand Up @@ -732,7 +738,7 @@ def find_all(self, identifier, *args, **kwargs):
if not recursive:
return to_return

for kind, key, _ in filter(lambda x: x[0] in ("list", "formatting") or (x[0] == "key" and isinstance(getattr(self, x[1]), Node)), self._render()):
for kind, key, _ in filter(lambda x: x[0] in ("list", "formatting") or (x[0] == "key" and isinstance(getattr(self, x[1]), Node)), self._render):
if kind == "key":
i = getattr(self, key)
if not i:
Expand Down Expand Up @@ -766,7 +772,7 @@ def parent_find(self, identifier, *args, **kwargs):
return None

def _node_match_query(self, node, identifier, *args, **kwargs):
if not self._attribute_match_query(node._generate_identifiers(), identifier.lower() if isinstance(identifier, string_instance) and not identifier.startswith("re:") else identifier):
if not self._attribute_match_query(node._identifiers, identifier.lower() if isinstance(identifier, string_instance) and not identifier.startswith("re:") else identifier):
return False

all_my_keys = node._str_keys + node._list_keys + node._dict_keys
Expand Down Expand Up @@ -829,14 +835,6 @@ def find_by_path(self, path):
def path(self):
return Path(self)

def _generate_identifiers(self):
return sorted(set(map(lambda x: x.lower(), [
self.type,
self.__class__.__name__,
self.__class__.__name__.replace("Node", ""),
self.type + "_"
] + self._other_identifiers)))

def _get_helpers(self):
not_helpers = set([
'copy',
Expand Down Expand Up @@ -905,7 +903,7 @@ def __help__(self, deep=2, with_formatting=False):
if not deep:
to_join[-1] += " ..."
else:
to_join.append("# identifiers: %s" % ", ".join(self._generate_identifiers()))
to_join.append("# identifiers: %s" % ", ".join(self._identifiers))
if self._get_helpers():
to_join.append("# helpers: %s" % ", ".join(self._get_helpers()))
if self._default_test_value != "value":
Expand Down Expand Up @@ -976,10 +974,6 @@ def __setattr__(self, name, value):

return super(Node, self).__setattr__(name, value)


def _render(self):
return nodes_rendering_order[self.type]

def replace(self, new_node):
new_node = self._convert_input_to_node_object(new_node, parent=None, on_attribute=None, generic=True)
self.__class__ = new_node.__class__ # YOLO
Expand Down
2 changes: 1 addition & 1 deletion tests/test_initial_parsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def test_assign_on_object_value_fst():

def test_generate_helpers():
red = RedBaron("def a(): pass")
assert set(red[0]._generate_identifiers()) == set([
assert set(red[0]._identifiers) == set([
"funcdef", "funcdef_", "defnode", "def", "def_"
])

Expand Down