Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
Fancy parser
-
I have this middle-sized data structure that I want to maintain in a format that does not contain any extra parentheses or curly braces. Here is a small sample:
_rules = """ left: type: leading target: attribute: x leading: value source: regular: view.x container: view.bounds.x right: type: trailing target: attribute: x and_so_on: ... """
This is nice to edit as Pythonista editor helps with the indentation.
Then I of course want to turn it into the corresponding Python data structure for usage, i.e. something like this:
{ "left": { "type": "leading", "target": { "attribute": "x", "leading": "value", "trailing": "value + gap", "flex": etc...
I did not want to bring in yaml as a dependency, so instead wrote the very fancy parser below, shared here in case someone else has a similar need, or knows of a smarter way to go about this type of thing.
import re def parse_rules(rules): rule_dict = dict() dicts = [rule_dict] spaces = re.compile(' *') for i, line in enumerate(rules.splitlines()): i += 11 # Used to match error line number to my file if line.strip() == '': continue indent = len(spaces.match(line).group()) if indent % 4 != 0: raise RuntimeError(f'Broken indent on line {i}') indent = indent // 4 + 1 if indent > len(dicts): raise RuntimeError(f'Extra indentation on line {i}') dicts = dicts[:indent] line = line.strip() if line.endswith(':'): key = line[:-1].strip() new_dict = dict() dicts[-1][key] = new_dict dicts.append(new_dict) else: try: key, content = line.split(':') dicts[-1][key.strip()] = content.strip() except Exception as error: raise RuntimeError(f'Cannot parse line {i}', error) return rule_dict
I only need the contents as strings, but for other use cases you might throw in an
eval
around thecontent
to support numbers, strings, lists and whatnot.