diff --git a/changelog.rst b/changelog.rst index 667ef32..fc08ae9 100644 --- a/changelog.rst +++ b/changelog.rst @@ -1,6 +1,19 @@ Changelog ========= +Version 0.1.7 (6th Apr 2024) +---------------------------- + +* Correct wront assumptions in the code (fix #5) + + +Version 0.1.6 (21th Dec 2023) +---------------------------- + +* Cleanup some typing and var names +* Implement `__contains__` and `__delitem__` (partial fix for #4) + + Version 0.1.5 (18th Dec 2023) ---------------------------- diff --git a/tests.py b/tests.py index 1e2861a..2135d1e 100644 --- a/tests.py +++ b/tests.py @@ -3,7 +3,7 @@ """ try: - from typing import Optional + from typing import Dict, Optional except ImportError: pass @@ -82,7 +82,7 @@ def __init__( self, input_: str, label: str, - output: Optional[str] = None, + output: Optional[Dict] = None, message: Optional[str] = None, ): self.input = input_ @@ -169,6 +169,22 @@ def run(self): "list": {"nesting": {"nested_and_empty": [[], [[]]]}}, }, ), + Test( + """ + [card] + bg = "tv" + text = "This is a different card." + options = [ ["(B)ack", "main"] ] + """, + label="Issue #5", + output={ + "card": { + "bg": "tv", + "text": "This is a different card.", + "options": [["(B)ack", "main"]] + }, + }, + ) ] diff --git a/toml/__init__.py b/toml/__init__.py index f5f2cb9..2c9559f 100644 --- a/toml/__init__.py +++ b/toml/__init__.py @@ -1,4 +1,4 @@ __author__ = "elpekenin" -__version__ = (0, 1, 6) +__version__ = (0, 1, 7) from ._toml import * diff --git a/toml/_toml.py b/toml/_toml.py index d8e7857..67cf445 100644 --- a/toml/_toml.py +++ b/toml/_toml.py @@ -47,12 +47,6 @@ class LineInfo: tokens: dict """Mapping from tokens to the position(s) where they are found on the line.""" - open_quote: int = -1 - """Position of the first " or ' found, -1 if none.""" - - close_quote: int = -1 - """Position of the closing " or ', -1 if none.""" - assignment: int = -1 """Position of the equal sign, -1 if none.""" @@ -64,6 +58,7 @@ def __init__(self, __line: str): self.tokens = {t: [] for t in Tokens.ALL} in_quotes = False + quote_token = None for i, char in enumerate(__line.lstrip()): # upon finding a comment (not in a quoted string), quit if char == Tokens.COMMENT and not in_quotes: @@ -75,15 +70,20 @@ def __init__(self, __line: str): # add current char to "clean" string self.line += char - # keep track of opening quote - if char in Tokens.QUOTES and self.open_quote == -1: - in_quotes = True - self.open_quote = i - - # ... and where it ends - if in_quotes and i != self.open_quote and char == __line[self.open_quote]: - in_quotes = False - self.close_quote = i + if char in Tokens.QUOTES: + # opening quote + if not quote_token: + in_quotes = True + quote_token = char + self.tokens[char].append(i) + continue + + # closing quote + elif char == quote_token: + in_quotes = False + quote_token = None + self.tokens[char].append(i) + continue # no token data to be stored if we are in a string if in_quotes: @@ -112,11 +112,11 @@ def check(info: LineInfo) -> Optional[str]: # String checks # ################# - # smallest (but not -1) index - quoted = info.open_quote != -1 + single = len(info.tokens[Tokens.SINGLE_QUOTE]) + double = len(info.tokens[Tokens.DOUBLE_QUOTE]) - # there can only be 2 delimiting quotes (open and close), but an arbritrary amount of the other one - if quoted and info.line.count(info.line[info.open_quote]) != 2: + # every openning quote should be closed too + if single % 2 != 0 or double % 2 != 0: return "Malformed string, check out your quotes" ####################### @@ -219,6 +219,9 @@ def _parse_value(self, __value: str, __line_info: Optional[LineInfo] = None) -> __value[0] == Tokens.OPENING_BRACKET and __value[-1] == Tokens.CLOSING_BRACKET ): + if __line_info is None: + raise TOMLError("How did we end on array parsing without line info?") + opening = __line_info.tokens[Tokens.OPENING_BRACKET] closing = __line_info.tokens[Tokens.CLOSING_BRACKET] @@ -256,8 +259,9 @@ def _parse_list(self, __line: str, __start: int) -> tuple[list[Any], int]: # early stop when current list ends if char == Tokens.CLOSING_BRACKET: - if text: - elements.append(self._parse_value(text.strip())) + _text = text.strip() + if _text: + elements.append(self._parse_value(_text)) return elements, pos # parse list and update current position @@ -269,8 +273,9 @@ def _parse_list(self, __line: str, __start: int) -> tuple[list[Any], int]: # parse the element we have collected so far elif char == Tokens.COMMA: - if text: - elements.append(self._parse_value(text.strip())) + _text = text.strip() + if _text: + elements.append(self._parse_value(_text)) text = "" # collect another char