diff --git a/redstring/parser.py b/redstring/parser.py index 4fad427..7a24e7d 100644 --- a/redstring/parser.py +++ b/redstring/parser.py @@ -125,7 +125,7 @@ class DocumentTab: """ A division of tags within a document. """ - def __init__(self, tags: List[DocumentTag], options: TabOptions) -> None: + def __init__(self, name: str, tags: List[DocumentTag], options: TabOptions) -> None: self.tags: List[DocumentTag] = tags self.options: TabOptions = options @@ -153,7 +153,9 @@ def load(fd: IO) -> Document: """ Load a document from a file descriptor. """ - parsed_json: list = json.load(fd, object_pairs_hook=OrderedDict) + parsed_json = json.load(fd, object_pairs_hook=OrderedDict) + if not isinstance(parsed_json, list): + raise ValueError('Parsing as document, expected list') return parse_document_from_json(parsed_json) @@ -161,7 +163,9 @@ def loads(string: str) -> Document: """ Load a document from a string. """ - parsed_json: list = json.loads(string, object_pairs_hook=OrderedDict) + parsed_json = json.loads(string, object_pairs_hook=OrderedDict) + if not isinstance(parsed_json, list): + raise ValueError('Parsing as document, expected list') return parse_document_from_json(parsed_json) @@ -172,8 +176,8 @@ def parse_document_from_json(parsed_json: list) -> Document: # Parse tabs tabs: List[DocumentTab] = [] for tab_json in parsed_json: - if type(tab_json) is not dict: - raise ValueError() + if not isinstance(tab_json, dict): + raise ValueError(f'Parsing tab, expected dict but got {type(tab_json)}') tabs.append(parse_tab_from_json(tab_json)) return Document(tabs) @@ -183,23 +187,27 @@ def parse_tab_from_json(tab_json: dict) -> DocumentTab: """ Parses JSON into a DocumentTab object. """ + # Parse tab name + if 'name' not in tab_json: + raise ValueError('Expected tab name') + name: str = tab_json['name'] + # Parse tab options - if 'options' not in tab_json: - raise ValueError() - options_json: dict = tab_json['options'] + options_json: dict = {} + if 'options' in tab_json: + options_json = tab_json['options'] options: TabOptions = TabOptions(**options_json) # Parse tags - if 'tags' not in tab_json: - raise ValueError() - tags_json: list = tab_json['tags'] tags: List[DocumentTag] = [] - for tag_json in tags_json: - if type(tag_json) is not dict: - raise ValueError() - tags.append(parse_tag_from_json(tag_json)) + if 'tags' in tab_json: + tags_json: list = tab_json['tags'] + for tag_json in tags_json: + if not isinstance(tag_json, dict): + raise ValueError(f'Parsing tag, expected dict but got {type(tag_json)}') + tags.append(parse_tag_from_json(tag_json)) - return DocumentTab(tags, options) + return DocumentTab(name, tags, options) def parse_tag_from_json(tag_json: dict) -> DocumentTag: @@ -208,29 +216,28 @@ def parse_tag_from_json(tag_json: dict) -> DocumentTag: """ # Parse name if 'name' not in tag_json: - raise ValueError() + raise ValueError('Expected tag name') name: str = tag_json['name'] # Parse value - if 'value' not in tag_json: - raise ValueError() - value: str = tag_json['value'] + value: str = '' + if 'value' in tag_json: + value = tag_json['value'] # Parse tag options - if 'options' not in tag_json: - raise ValueError() - options_json: dict = tag_json['options'] + options_json: dict = {} + if 'options' in tag_json: + options_json = tag_json['options'] options: TagOptions = TagOptions(**options_json) # Parse subtags - if 'subtags' not in tag_json: - raise ValueError() - subtags_json: list = tag_json['subtags'] subtags: List[DocumentSubtag] = [] - for subtag_json in subtags_json: - if type(subtag_json) is not dict: - raise ValueError() - subtags.append(parse_subtag_from_json(subtag_json)) + if 'subtags' in tag_json: + subtags_json: list = tag_json['subtags'] + for subtag_json in subtags_json: + if not isinstance(subtag_json, dict): + raise ValueError(f'Parsing subtag, expected dict but got {type(subtag_json)}') + subtags.append(parse_subtag_from_json(subtag_json)) return DocumentTag(name, value, options, subtags) @@ -241,18 +248,18 @@ def parse_subtag_from_json(subtag_json: dict) -> DocumentSubtag: """ # Parse name if 'name' not in subtag_json: - raise ValueError() + raise ValueError('Expected subtag name') name: str = subtag_json['name'] # Parse value - if 'value' not in subtag_json: - raise ValueError() - value: str = subtag_json['value'] + value: str = '' + if 'value' in subtag_json: + value = subtag_json['value'] # Parse tag options - if 'options' not in subtag_json: - raise ValueError() - options_json: dict = subtag_json['options'] + options_json: dict = {} + if 'options' in subtag_json: + options_json = subtag_json['options'] options: TagOptions = TagOptions(**options_json) return DocumentSubtag(name, value, options) @@ -272,8 +279,8 @@ def check(files): try: load(f) print(f'OK {file}') - except: - print(f'ERROR {file}') + except Exception as ex: + print(f'ERROR {file} - {ex}') def main() -> Any: