Ejemplo n.º 1
0
def to_entry(name, attrs, body):
    if body == ";":
        return Entry(name=name.value, attrs=attrs, lineno=name.lineno)
    return Entry(name=name.value,
                 attrs=attrs,
                 children=body,
                 lineno=name.lineno)
Ejemplo n.º 2
0
 def to_entry(name, rest):
     if isinstance(rest, list):
         return Entry(name=name.value,
                      children=rest,
                      lineno=name.lineno,
                      src=ctx)
     return Entry(name=name.value,
                  attrs=[rest],
                  lineno=name.lineno,
                  src=ctx)
Ejemplo n.º 3
0
def parse_doc(content, ctx=None):
    """ Parse a configuration document into a tree that can be queried. """
    if isinstance(content, list):
        content = "\n".join(content)
    parse = DocParser(ctx)
    result = parse(content)[0]
    return Entry(children=result, src=ctx)
Ejemplo n.º 4
0
def parse_doc(f, ctx=None, line_end="\n"):
    def to_entry(name, rest):
        if isinstance(rest, list):
            return Section(name=name.value,
                           children=rest,
                           lineno=name.lineno,
                           src=ctx)
        return Directive(name=name.value,
                         attrs=[rest],
                         lineno=name.lineno,
                         src=ctx)

    Sep = InSet(":=")
    Stmt = Forward()
    Num = Number & (WSChar | LineEnd)
    NULL = Literal("none", value=None)
    Comment = (WS >> OneLineComment("#").map(lambda x: None))
    BeginBlock = (WS >> LeftCurly << WS)
    EndBlock = (WS >> RightCurly << WS)
    Bare = String(
        set(string.printable) - (set(string.whitespace) | set("#{}'\"")))
    Name = WS >> PosMarker(
        String(string.ascii_letters + "_" + string.digits)) << WS
    Value = WS >> (Num | NULL | QuotedString | Bare) << WS
    Block = BeginBlock >> Many(Stmt).map(skip_none) << EndBlock
    Stanza = (Lift(to_entry) * Name * (Block | (Sep >> Value))) | Comment
    Stmt <= WS >> Stanza << WS
    Doc = Many(Stmt).map(skip_none)
    Top = Doc + EOF

    return Entry(children=Top(f)[0], src=ctx)
Ejemplo n.º 5
0
def parse_doc(content, ctx):
    def to_directive(x):
        name, rest = x
        rest = [rest] if rest is not None else []
        return Directive(name=name.value.strip(),
                         attrs=rest,
                         lineno=name.lineno,
                         src=ctx)

    def to_section(name, rest):
        return Section(name=name.value.strip(),
                       children=rest,
                       lineno=name.lineno,
                       src=ctx)

    def apply_defaults(cfg):
        if "DEFAULT" not in cfg:
            return cfg

        defaults = cfg["DEFAULT"]
        not_defaults = cfg[~eq("DEFAULT")]
        for c in not_defaults:
            for d in defaults.grandchildren:
                if d.name not in c:
                    c.children.append(d)

        cfg.children = list(not_defaults)
        return cfg

    header_chars = (set(string.printable) - set(string.whitespace) -
                    set("[]")) | set(" ")
    sep_chars = set("=:")
    key_chars = header_chars - sep_chars
    value_chars = set(string.printable) - set("\n\r")

    Yes = Literal("yes", True, ignore_case=True)
    No = Literal("no", False, ignore_case=True)
    Tru = Literal("true", True, ignore_case=True)
    Fals = Literal("false", False, ignore_case=True)
    Boolean = ((Yes | No | Tru | Fals) & (WSChar | LineEnd)) % "Boolean"

    LeftEnd = (WS + LeftBracket + WS)
    RightEnd = (WS + RightBracket + WS)
    Header = (
        LeftEnd >> PosMarker(String(header_chars)) << RightEnd) % "Header"
    Key = WS >> PosMarker(String(key_chars)) << WS
    Sep = InSet(sep_chars, "Sep")
    Value = WS >> (Boolean | HangingString(value_chars))
    KVPair = WithIndent(Key + Opt(Sep >> Value)) % "KVPair"
    Comment = (WS >>
               (OneLineComment("#") | OneLineComment(";")).map(lambda x: None))

    Line = Comment | KVPair.map(to_directive)
    Sect = Lift(to_section) * Header * Many(Line).map(skip_none)
    Doc = Many(Comment | Sect).map(skip_none)
    Top = Doc + EOF

    res = Entry(children=Top(content)[0], src=ctx)
    return apply_defaults(res)
Ejemplo n.º 6
0
def parse_doc(f, ctx=None, line_end="\n"):
    def to_entry(name, rest):
        rest = [] if not rest else [rest]
        return Directive(name=name.value, attrs=rest, lineno=name.lineno, src=ctx)

    Sep = Char("=")
    Stmt = Forward()
    Num = Number & (WSChar | LineEnd)
    Comment = (WS >> OneLineComment("#").map(lambda x: None))
    Bare = String(set(string.printable) - (set("#\n\r")))
    Name = WS >> PosMarker(String(string.ascii_letters + "_-" + string.digits)) << WS
    Value = WS >> (Num | Bare) << WS
    Stanza = (Lift(to_entry) * Name * (Opt(Sep >> Value))) | Comment
    Stmt <= WS >> Stanza << WS
    Doc = Many(Stmt).map(skip_none)
    Top = Doc + EOF

    return Entry(children=Top(f)[0], src=ctx)
Ejemplo n.º 7
0
 def parse_doc(self, content):
     if isinstance(content, list):
         content = "\n".join(content)
     result = self.parse(content)[0]
     return Entry(children=result, src=self)
Ejemplo n.º 8
0
from insights.parsr.query import all_, any_, compile_queries, Entry, lt

complex_tree = Entry(name="root",
                    attrs=[1, 2, 3, 4],
                    children=[
                        Entry(name="child", attrs=[1, 1, 2]),
                        Entry(name="child", attrs=[1, 1, 2, 3, 5]),
                        Entry(name="child", attrs=[1, 1, 3, 5, 9]),
                        Entry(name="dog", attrs=["woof"], children=[
                            Entry(name="puppy", attrs=["smol"]),
                            Entry(name="puppy", attrs=["fluffy"]),
                            Entry(name="kitten", attrs=["wut"]),
                        ])
                    ])


def test_complex():
    t = complex_tree

    q = compile_queries("child")
    assert len(q(t.children)) == 3

    q = compile_queries(("child", 3))
    assert len(q(t.children)) == 2

    q = compile_queries(("child", all_(lt(3))))
    assert len(q(t.children)) == 1

    q = compile_queries(("child", any_(1)))
    assert len(q(t.children)) == 3
Ejemplo n.º 9
0
    def parse_doc(self, content):
        try:
            def to_directive(x):
                name, rest = x
                rest = [rest] if rest is not None else []
                return Directive(name=name.value.strip(), attrs=rest, lineno=name.lineno, src=self)

            def to_section(name, rest):
                return Section(name=name.value.strip(), children=rest, lineno=name.lineno, src=self)

            def apply_defaults(cfg):
                if "DEFAULT" not in cfg:
                    return cfg

                defaults = cfg["DEFAULT"]
                not_defaults = cfg[~eq("DEFAULT")]
                for c in not_defaults:
                    for d in defaults.grandchildren:
                        if d.name not in c:
                            c.children.append(d)

                cfg.children = list(not_defaults)
                return cfg

            def make_bytes(number, char_multiple):
                if char_multiple.lower() == 'k':
                    return number * 2**10
                if char_multiple.lower() == 'm':
                    return number * 2**20
                if char_multiple.lower() == 'g':
                    return number * 2**30

            content = "\n".join(content)

            header_chars = (set(string.printable) - set(string.whitespace) - set("[]")) | set(" ")
            sep_chars = set("=")
            key_chars = header_chars - sep_chars
            value_chars = set(string.printable) - set("\n\r")

            On = Literal("on", True, ignore_case=True)
            Off = Literal("off", False, ignore_case=True)
            Tru = Literal("true", True, ignore_case=True)
            Fals = Literal("false", False, ignore_case=True)
            Boolean = ((On | Off | Tru | Fals) & (WSChar | LineEnd)) % "Boolean"
            Num = Number & (WSChar | LineEnd)
            QuoStr = QuotedString & (WSChar | LineEnd)
            # Handle php.ini shorthand notation for memory limits: 1G, 8M, 50K
            # https://www.php.net/manual/en/faq.using.php#faq.using.shorthandbytes
            MemNum = (Lift(make_bytes) * Number * (Char('K') | Char('M') | Char('G'))) & (WSChar | LineEnd)

            LeftEnd = (WS + LeftBracket + WS)
            RightEnd = (WS + RightBracket + WS)
            Header = (LeftEnd >> PosMarker(String(header_chars)) << RightEnd) % "Header"
            Key = WS >> PosMarker(String(key_chars)) << WS
            Sep = InSet(sep_chars, "Sep")
            Value = WS >> (Boolean | MemNum | Num | QuoStr | HangingString(value_chars))
            KVPair = WithIndent(Key + Opt(Sep >> Value)) % "KVPair"
            Comment = (WS >> (OneLineComment(";")).map(lambda x: None))

            Line = Comment | KVPair.map(to_directive)
            Sect = Lift(to_section) * Header * Many(Line).map(skip_none)
            Doc = Many(Comment | Sect).map(skip_none)
            Top = Doc << WS << EOF

            res = Entry(children=Top(content), src=self)
            return apply_defaults(res)

        except SkipException:
            raise
        except:
            raise ParseException(ParseException("Could not parse content: '{0}'".
                                                format(content)))
Ejemplo n.º 10
0
def loads(data):
    return Entry(children=Top(data))
Ejemplo n.º 11
0
def to_entry(ms):
    children = []
    for mark, value in ms:
        children.append(
            Entry(name=mark.value, attrs=[value], lineno=mark.lineno))
    return Entry(children=children)
Ejemplo n.º 12
0
 def parse_doc(self, content):
     return Entry(children=self.Top("\n".join(content))[0], src=self)