Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a VDF) to a Python object. ``mapper`` specifies the Python object used after deserializetion. ``dict` is used by default. Alternatively, ``collections.OrderedDict`` can be used if you wish to preserve key order. Or any
(fp, mapper=dict, merge_duplicate_keys=True, escaped=True)
| 75 | |
| 76 | # parsing and dumping for KV1 |
| 77 | def parse(fp, mapper=dict, merge_duplicate_keys=True, escaped=True): |
| 78 | """Deserialize ``s`` (a ``str`` or ``unicode`` instance containing a VDF) |
| 79 | to a Python object. |
| 80 | |
| 81 | ``mapper`` specifies the Python object used after deserializetion. ``dict` is |
| 82 | used by default. Alternatively, ``collections.OrderedDict`` can be used if you |
| 83 | wish to preserve key order. Or any object that acts like a ``dict``. |
| 84 | |
| 85 | ``merge_duplicate_keys`` when ``True`` will merge multiple KeyValue lists with the |
| 86 | same key into one instead of overwriting. You can se this to ``False`` if you are |
| 87 | using ``VDFDict`` and need to preserve the duplicates. |
| 88 | """ |
| 89 | if not issubclass(mapper, Mapping): |
| 90 | raise TypeError("Expected mapper to be subclass of dict, got %s" % type(mapper)) |
| 91 | if not hasattr(fp, "readline"): |
| 92 | raise TypeError( |
| 93 | "Expected fp to be a file-like object supporting line iteration" |
| 94 | ) |
| 95 | |
| 96 | stack = [mapper()] |
| 97 | expect_bracket = False |
| 98 | |
| 99 | re_keyvalue = re.compile( |
| 100 | r'^("(?P<qkey>(?:\\.|[^\\"])*)"|(?P<key>#?[a-z0-9\-\_\\\?$%<>]+))' |
| 101 | r"([ \t]*(" |
| 102 | r'"(?P<qval>(?:\\.|[^\\"])*)(?P<vq_end>")?' |
| 103 | r"|(?P<val>(?:(?<!/)/(?!/)|[a-z0-9\-\_\\\?\*\.$<> ])+)" |
| 104 | r"|(?P<sblock>{[ \t]*)(?P<eblock>})?" |
| 105 | r"))?", |
| 106 | flags=re.IGNORECASE, |
| 107 | ) |
| 108 | |
| 109 | for lineno, line in enumerate(fp, 1): |
| 110 | if lineno == 1: |
| 111 | line = strip_bom(line) |
| 112 | |
| 113 | line = line.lstrip() |
| 114 | |
| 115 | # skip empty and comment lines |
| 116 | if line == "" or line[0] == "/": |
| 117 | continue |
| 118 | |
| 119 | # one level deeper |
| 120 | if line[0] == "{": |
| 121 | expect_bracket = False |
| 122 | continue |
| 123 | |
| 124 | if expect_bracket: |
| 125 | raise SyntaxError( |
| 126 | "vdf.parse: expected openning bracket", |
| 127 | (getattr(fp, "name", "<%s>" % fp.__class__.__name__), lineno, 1, line), |
| 128 | ) |
| 129 | |
| 130 | # one level back |
| 131 | if line[0] == "}": |
| 132 | if len(stack) > 1: |
| 133 | stack.pop() |
| 134 | continue |