def _string_to_node(self, string, parent, on_attribute): if on_attribute == "exception": if string: self.first_formatting = [Node.from_fst({"type": "space", "value": " "}, on_attribute=on_attribute, parent=parent)] return Node.from_fst(baron.parse("try: pass\nexcept %s: pass" % string)[0]["excepts"][0]["exception"], parent=parent, on_attribute=on_attribute) else: self.first_formatting = [] self.delimiter = "" self.target = "" return "" elif on_attribute == "target": if not self.exception: raise Exception("Can't set a target to an exception node that doesn't have an exception set") if string: self.delimiter = "as" self.second_formatting = [Node.from_fst({"type": "space", "value": " "}, on_attribute=on_attribute, parent=parent)] self.third_formatting = [Node.from_fst({"type": "space", "value": " "}, on_attribute=on_attribute, parent=parent)] return Node.from_fst(baron.parse("try: pass\nexcept a as %s: pass" % string)[0]["excepts"][0]["target"], parent=parent, on_attribute=on_attribute) else: self.delimiter = "" self.second_formatting = [] self.third_formatting = [] return "" else: raise Exception("Unhandled case")
def _parse_indented(self, value, replace=False): if replace: implicit_indent = self.indentation + self.default_indent else: implicit_indent = self.el_indentation value = indent_str(value, implicit_indent) # First line is on the same line with def/class element # we do not want to the el_indentation there # e.g def f(): {value} if value.startswith(" ") and value.lstrip(" ").startswith("\n"): leading_endl = "" value = value[len(implicit_indent):] else: leading_endl = "\n" # Handle the case of empty lines if strip_comments(value.strip(" \n")): fst = baron.parse("while a:%s%s" % (leading_endl, value)) trailing_endl = fst[1:] fst = fst[0]['value'] if leading_endl: fst[0] = {"type": "space", "value": fst[0]['indent']} fst += trailing_endl else: fst = baron.parse(value) return fst
def _string_to_node_list(self, string, parent, on_attribute): fst = baron.parse("(%s)" % string)[0]["value"] # I assume that I've got an AssociativeParenthesisNode here instead of a tuple # because string is only one single element if not isinstance(fst, list): fst = baron.parse("(%s,)" % string)[0]["value"] return NodeList.from_fst(fst, parent=parent, on_attribute=on_attribute)
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "iterator": return Node.from_fst(baron.parse("[x for %s in x]" % string)[0]["generators"][0]["iterator"], parent=parent, on_attribute=on_attribute) elif on_attribute == "target": return Node.from_fst(baron.parse("[x for s in %s]" % string)[0]["generators"][0]["target"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "value": return Node.from_fst(baron.parse("def a(b=%s): pass" % string)[0]["arguments"][0]["value"], parent=parent, on_attribute=on_attribute) if string else "" elif on_attribute == "target": return Node.from_fst(baron.parse("def a(%s=b): pass" % string)[0]["arguments"][0]["target"], parent=parent, on_attribute=on_attribute) if string else "" else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "first": return Node.from_fst(baron.parse("%s and b" % string)[0]["first"], parent=parent, on_attribute=on_attribute) elif on_attribute == "second": return Node.from_fst(baron.parse("bb and %s" % string)[0]["second"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "target": return Node.from_fst(baron.parse("%s = a" % string)[0]["target"], parent=parent, on_attribute=on_attribute) elif on_attribute == "value": return Node.from_fst(baron.parse("a = %s" % string)[0]["value"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "value": return Node.from_fst(baron.parse("{a: %s}" % string)[0]["value"][0]["value"], parent=parent, on_attribute=on_attribute) elif on_attribute == "key": return Node.from_fst(baron.parse("{%s: a}" % string)[0]["value"][0]["key"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "target": return Node.from_fst(baron.parse("for i in %s: pass" % string)[0]["target"], parent=parent, on_attribute=on_attribute) elif on_attribute == "iterator": return Node.from_fst(baron.parse("for %s in i: pass" % string)[0]["iterator"], parent=parent, on_attribute=on_attribute) else: return super(ForNode, self)._string_to_node(string, parent, on_attribute)
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "value": return Node.from_fst(baron.parse("@%s()\ndef a(): pass" % string)[0]["decorators"][0]["value"], parent=parent, on_attribute=on_attribute) elif on_attribute == "call": if string: return Node.from_fst(baron.parse("@a%s\ndef a(): pass" % string)[0]["decorators"][0]["call"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def test_error_bad_indentation(): """ Regression test case It shows a discrepency between python2 and python3 in string comparisons with None. """ with pytest.raises(ParsingError): parse("def fun():\nass") with pytest.raises(BaronError): parse("def fun():\nass")
def value(self, value): fst = baron.parse("(%s)" % value)[0]["value"] # I assume that I've got an AssociativeParenthesisNode here instead # of a tuple because string is only one single element if not isinstance(fst, list): assert fst["type"] == "associativeparenthesis" fst = baron.parse("(%s,)" % value)[0]["value"] return fst
def _string_to_node_list(self, string, parent, on_attribute): if on_attribute == "targets": fst = baron.parse("from a import %s" % string)[0]["targets"] return NodeList.from_fst(fst, parent=parent, on_attribute=on_attribute) if on_attribute == "value": fst = baron.parse("from %s import s" % string)[0]["value"] return NodeList.from_fst(fst, parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "value": return Node.from_fst(baron.parse("assert %s" % string)[0]["value"], parent=parent, on_attribute=on_attribute) elif on_attribute == "message": if string: self.third_formatting = [Node.from_fst({"type": "space", "value": " "}, on_attribute=on_attribute, parent=parent)] return Node.from_fst(baron.parse("assert plop, %s" % string)[0]["message"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _parse_inline(self, value): if value.rstrip("\n").count("\n"): raise ValueError("inline code can't have multiple lines") if strip_comments(value.strip(" \n")): fst = baron.parse("while a: %s" % value)[0] indent = fst['third_formatting'][0]['value'][1:] else: fst = {"value": [baron.parse(value)[0]]} indent = fst['formatting'][0]['value'] if value.startswith( " ") else "" fst['value'].insert(0, {"type": "space", "value": indent}) return fst["value"]
def _string_to_node_list(self, string, parent, on_attribute): if on_attribute != "excepts": return super(TryNode, self)._string_to_node_list(string, parent=parent, on_attribute=on_attribute) clean_string = re.sub("^ *\n", "", string) if "\n" in string else string indentation = len(re.search("^ *", clean_string).group()) if indentation: string = "\n".join(map(lambda x: x[indentation:], string.split("\n"))) string = string.rstrip() string += "\n" if self.next and self.on_attribute == "root": string += "\n\n" elif self.next: string += "\n" result = NodeList.from_fst(baron.parse("try:\n pass\n%sfinally:\n pass" % string)[0]["excepts"], parent=parent, on_attribute=on_attribute) if self.indentation: result.increase_indentation(len(self.indentation)) if self._get_last_member_to_clean().type != "except": # assume that this is an endl node, this might break result[-1].value.node_list[-1].indent = self.indentation elif self.next: result[-1].value.node_list[-1].indent = self.indentation return result
def __init__(self, source_code): self.first_blank_lines = [] # XXX might need changes if isinstance(source_code, string_instance): self.node_list = base_nodes.NodeList.from_fst( baron.parse(source_code), parent=self, on_attribute="root") self.middle_separator = nodes.DotNode({ "type": "endl", "formatting": [], "value": "\n", "indent": "" }) self.data = [] previous = None for i in self.node_list: if i.type != "endl": self.data.append([i, []]) elif previous and previous.type == "endl": self.data.append([previous, []]) elif previous is None and i.type == "endl": self.data.append([i, []]) elif self.data: self.data[-1][1].append(i) previous = i self.node_list.parent = None else: # Might be init from same object, or slice super(RedBaron, self).__init__(source_code) self.on_attribute = None self.parent = None
def __init__(self, source_code): self.first_blank_lines = [] # XXX might need changes if isinstance(source_code, string_instance): self.node_list = base_nodes.NodeList.from_fst(baron.parse(source_code), parent=self, on_attribute="root") self.middle_separator = nodes.DotNode({"type": "endl", "formatting": [], "value": "\n", "indent": ""}) self.data = [] previous = None for i in self.node_list: if i.type != "endl": self.data.append([i, []]) elif previous and previous.type == "endl": self.data.append([previous, []]) elif previous is None and i.type == "endl": self.data.append([i, []]) elif self.data: self.data[-1][1].append(i) previous = i self.node_list.parent = None else: # Might be init from same object, or slice super(RedBaron, self).__init__(source_code) self.on_attribute = None self.parent = None
def _string_to_node_list(self, string, parent, on_attribute): if on_attribute == "generators": fst = baron.parse("{x %s}" % string)[0]["generators"] return NodeList.from_fst(fst, parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def _string_to_node_list(self, string, parent, on_attribute): if on_attribute != "value": return super(IfelseblockNode, self)._string_to_node_list(string, parent=parent, on_attribute=on_attribute) string = string.rstrip() string += "\n" if self.next and self.on_attribute == "root": string += "\n\n" elif self.next: string += "\n" clean_string = re.sub("^ *\n", "", string) if "\n" in string else string indentation = len(re.search("^ *", clean_string).group()) if indentation: string = "\n".join(map(lambda x: x[indentation:], string.split("\n"))) result = NodeList.from_fst(baron.parse(string)[0]["value"], parent=parent, on_attribute=on_attribute) if self.indentation: result.increase_indentation(len(self.indentation)) if self.next: result[-1].value.node_list[-1].indent = self.indentation return result
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "value": return Node.from_fst(baron.parse("with %s: pass" % string)[0]["contexts"][0]["value"], parent=parent, on_attribute=on_attribute) elif on_attribute == "as": if string: self.first_formatting = [{"type": "space", "value": " "}] self.second_formatting = [{"type": "space", "value": " "}] return Node.from_fst(baron.parse("with a as %s: pass" % string)[0]["contexts"][0]["as"], parent=parent, on_attribute=on_attribute) else: self.first_formatting = [] self.second_formatting = [] return "" else: raise Exception("Unhandled case")
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "lower": if string: return Node.from_fst(baron.parse("a[%s:]" % string)[0]["value"][1]["value"]["lower"], parent=parent, on_attribute=on_attribute) elif on_attribute == "upper": if string: return Node.from_fst(baron.parse("a[:%s]" % string)[0]["value"][1]["value"]["upper"], parent=parent, on_attribute=on_attribute) elif on_attribute == "step": self.has_two_colons = bool(string) if string: return Node.from_fst(baron.parse("a[::%s]" % string)[0]["value"][1]["value"]["step"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def locals(self, value): if not value: return None if not self.globals: raise Exception("I can't set locals when globals aren't set.") return baron.parse("exec a in b, %s" % value)[0]["locals"]
def generic_from_str(source_code: str, parent=None, on_attribute=None): assert isinstance(source_code, str) fst = baron.parse(source_code) assert len(fst) == 1 return Node.generic_from_fst(fst[0], parent=parent, on_attribute=on_attribute)
def test_walk_assignment(): node = parse("a = 1") walker = RenderWalkerTester([ ('>', 'node', 'assignment', 0, False), ('>', 'key', 'name', 'target', False), ('>', 'constant', 'a', 'value', False), ('<', 'constant', 'a', 'value', False), ('<', 'key', 'name', 'target', False), ('>', 'formatting', 'list', 'first_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'constant', ' ', 'value', False), ('<', 'constant', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'first_formatting', False), ('>', 'constant', '=', '=', False), ('<', 'constant', '=', '=', False), ('>', 'formatting', 'list', 'second_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'constant', ' ', 'value', False), ('<', 'constant', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'second_formatting', False), ('>', 'key', 'int', 'value', False), ('>', 'constant', '1', 'value', False), ('<', 'constant', '1', 'value', False), ('<', 'key', 'int', 'value', False), ('<', 'node', 'assignment', 0, False), ]) walker.walk(node)
def test_floating_point_parser_bug_85(): from baron import parse assert parse('d*e-1') == [{ 'first': { 'first': { 'type': 'name', 'value': 'd' }, 'first_formatting': [], 'second': { 'type': 'name', 'value': 'e' }, 'second_formatting': [], 'type': 'binary_operator', 'value': '*' }, 'first_formatting': [], 'second': { 'section': 'number', 'type': 'int', 'value': '1' }, 'second_formatting': [], 'type': 'binary_operator', 'value': '-' }]
def test_walk_assignment(): node = parse("a = 1") walker = RenderWalkerTester([ ('>', 'node', 'assignment', 0, False), ('>', 'key', 'name', 'target', False), ('>', 'string', 'a', 'value', False), ('<', 'string', 'a', 'value', False), ('<', 'key', 'name', 'target', False), ('>', 'formatting', 'list', 'first_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'string', ' ', 'value', False), ('<', 'string', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'first_formatting', False), ('>', 'constant', '=', '=', False), ('<', 'constant', '=', '=', False), ('>', 'formatting', 'list', 'second_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'string', ' ', 'value', False), ('<', 'string', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'second_formatting', False), ('>', 'key', 'int', 'value', False), ('>', 'string', '1', 'value', False), ('<', 'string', '1', 'value', False), ('<', 'key', 'int', 'value', False), ('<', 'node', 'assignment', 0, False), ]) walker.walk(node)
def _string_to_node_list(self, string, parent, on_attribute): if on_attribute == "arguments": self.first_formatting = [{"type": "space", "value": " "}] if string else [] fst = baron.parse("lambda %s: x" % string)[0]["arguments"] return NodeList.from_fst(fst, parent=parent, on_attribute=on_attribute) else: return super(DefNode, self)._string_to_node_list(string, parent, on_attribute)
def value(self, value): if not value: raise ValueError("print call cannot be empty") if value.lstrip(" ")[0] != "(": raise ValueError("print call must start with (") if value.rstrip(" ")[-1] != ")": raise ValueError("print call must end with )") return baron.parse("print%s" % value)[0]["value"]
def _string_to_node(self, string, parent, on_attribute): if on_attribute == "value": self.formatting = [{"type": "space", "value": " "}] if string else [] if string: return Node.from_fst(baron.parse("return %s" % string)[0]["value"], parent=parent, on_attribute=on_attribute) else: raise Exception("Unhandled case")
def target(self, value): if not self.exception: raise Exception("Can't set a target to an exception node " "that doesn't have an exception set") if value == "": return None code = "try: pass\nexcept a as %s: pass" % value return baron.parse(code)[0]["excepts"][0]["target"]
def test_comment_before_for(): code = """ for var in iter: pass # comment for var in iter: pass """ assert dumps(parse(code)) == code
def test_walk_stop(): node = parse("a = 1") walker = RenderWalkerTester([ ('>', 'node', 'assignment', 0, False), ('>', 'key', 'name', 'target', False), ('>', 'constant', 'a', 'value', True), ('<', 'key', 'name', 'target', False), ('<', 'node', 'assignment', 0, False), ]) walker.walk(node)
def test_missing_quote_yields_error(): with pytest.raises(UntreatedError): parse("'") with pytest.raises(UntreatedError): parse("'\n") with pytest.raises(UntreatedError): parse("'\n")
def test_floating_point_parser_bug_85(): from baron import parse assert parse('d*e-1') == [ {'first': {'first': {'type': 'name', 'value': 'd'}, 'first_formatting': [], 'second': {'type': 'name', 'value': 'e'}, 'second_formatting': [], 'type': 'binary_operator', 'value': '*'}, 'first_formatting': [], 'second': {'section': 'number', 'type': 'int', 'value': '1'}, 'second_formatting': [], 'type': 'binary_operator', 'value': '-'}]
def test_error_unexpected_formatting(): with pytest.raises(UnExpectedFormattingToken): parse(" a\nb")
def test_fst(): some_code = "ax + (z * 4)" red = RedBaron(some_code) assert baron.parse(some_code) == red.fst()
def format_code(source_code): return Dumper().dump_root(baron.parse(source_code))
def test_dummy_parse(): parse("pouet")
def test_error_unexpected_formatting(): with pytest.raises(ParsingError): parse(" a\nb") with pytest.raises(BaronError): parse(" a\nb")
def test_error_parsing_error(): with pytest.raises(ParsingError): parse("(")
def test_walk_funcdef_with_leading_space(): node = parse("""\ @deco def fun(arg1): pass """) walker = RenderWalkerTester([ ('>', 'node', 'endl', 0, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'constant', '\n', 'value', False), ('<', 'constant', '\n', 'value', False), ('>', 'constant', '', 'indent', False), ('<', 'constant', '', 'indent', False), ('<', 'node', 'endl', 0, False), ('>', 'node', 'funcdef', 1, False), ('>', 'list', 'list', 'decorators', False), ('>', 'node', 'decorator', 0, False), ('>', 'constant', '@', '@', False), ('<', 'constant', '@', '@', False), ('>', 'key', 'dotted_name', 'value', False), ('>', 'list', 'list', 'value', False), ('>', 'node', 'name', 0, False), ('>', 'constant', 'deco', 'value', False), ('<', 'constant', 'deco', 'value', False), ('<', 'node', 'name', 0, False), ('<', 'list', 'list', 'value', False), ('<', 'key', 'dotted_name', 'value', False), ('<', 'node', 'decorator', 0, False), ('>', 'node', 'endl', 1, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'constant', '\n', 'value', False), ('<', 'constant', '\n', 'value', False), ('>', 'constant', '', 'indent', False), ('<', 'constant', '', 'indent', False), ('<', 'node', 'endl', 1, False), ('<', 'list', 'list', 'decorators', False), ('>', 'constant', 'def', 'def', False), ('<', 'constant', 'def', 'def', False), ('>', 'formatting', 'list', 'first_formatting', False), ('>', 'node', 'space', 0, False), ('>', 'constant', ' ', 'value', False), ('<', 'constant', ' ', 'value', False), ('<', 'node', 'space', 0, False), ('<', 'formatting', 'list', 'first_formatting', False), ('>', 'constant', 'fun', 'name', False), ('<', 'constant', 'fun', 'name', False), ('>', 'formatting', 'list', 'second_formatting', False), ('<', 'formatting', 'list', 'second_formatting', False), ('>', 'constant', '(', '(', False), ('<', 'constant', '(', '(', False), ('>', 'formatting', 'list', 'third_formatting', False), ('<', 'formatting', 'list', 'third_formatting', False), ('>', 'list', 'list', 'arguments', False), ('>', 'node', 'def_argument', 0, False), ('>', 'constant', 'arg1', 'name', False), ('<', 'constant', 'arg1', 'name', False), ('<', 'node', 'def_argument', 0, False), ('<', 'list', 'list', 'arguments', False), ('>', 'formatting', 'list', 'fourth_formatting', False), ('<', 'formatting', 'list', 'fourth_formatting', False), ('>', 'constant', ')', ')', False), ('<', 'constant', ')', ')', False), ('>', 'formatting', 'list', 'fifth_formatting', False), ('<', 'formatting', 'list', 'fifth_formatting', False), ('>', 'constant', ':', ':', False), ('<', 'constant', ':', ':', False), ('>', 'formatting', 'list', 'sixth_formatting', False), ('<', 'formatting', 'list', 'sixth_formatting', False), ('>', 'list', 'list', 'value', False), ('>', 'node', 'endl', 0, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'constant', '\n', 'value', False), ('<', 'constant', '\n', 'value', False), ('>', 'constant', ' ', 'indent', False), ('<', 'constant', ' ', 'indent', False), ('<', 'node', 'endl', 0, False), ('>', 'node', 'pass', 1, False), ('>', 'constant', 'pass', 'type', False), ('<', 'constant', 'pass', 'type', False), ('<', 'node', 'pass', 1, False), ('>', 'node', 'endl', 2, False), ('>', 'formatting', 'list', 'formatting', False), ('<', 'formatting', 'list', 'formatting', False), ('>', 'constant', '\n', 'value', False), ('<', 'constant', '\n', 'value', False), ('>', 'constant', '', 'indent', False), ('<', 'constant', '', 'indent', False), ('<', 'node', 'endl', 2, False), ('<', 'list', 'list', 'value', False), ('<', 'node', 'funcdef', 1, False), ]) walker.walk(node)
def test_error_grouping(): with pytest.raises(GroupingError): parse(" (a\n b")
def test_error_untreated_error(): with pytest.raises(UntreatedError): parse("?")
def __init__(self, source_code): self.data = map(to_node, baron.parse(source_code))
def test_find_endl_functionnal(): assert find('endl', baron.parse("[a, b, c]")[0]["value"]) == None assert find('endl', baron.parse("[a, b,\n c]")[0]["value"]) == {'formatting': [], 'indent': ' ', 'type': 'endl', 'value': '\n'}