Skip to content

Commit

Permalink
Fix the way table names are parsed
Browse files Browse the repository at this point in the history
  • Loading branch information
sdispater committed Feb 28, 2020
1 parent de23e48 commit c07e876
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 12 deletions.
21 changes: 21 additions & 0 deletions tests/examples/json/table_names.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"Special \"table\"": {
"foo": "bar"
},
"BJ's Restaurant": {
"account": "dining"
},
"]": {
"foo": 1
},
"[bracket]": {
"bar": 2
},
"a": {
"b.c": {
"d": {
"baz": 3
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,12 @@ foo = "bar"

["BJ's Restaurant"]
account = "dining"

["]"]
foo = 1

[ "[bracket]" ]
bar = 2

[ a . "b.c" . d ]
baz = 3
4 changes: 2 additions & 2 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,15 +53,15 @@ def json_serial(obj):
"newline_in_strings",
"preserve_quotes_in_string",
"string_slash_whitespace_newline",
"table_names_with_string_delimiters",
"table_names",
],
)
def test_parse_can_parse_valid_toml_files(example, example_name):
assert isinstance(parse(example(example_name)), TOMLDocument)
assert isinstance(loads(example(example_name)), TOMLDocument)


@pytest.mark.parametrize("example_name", ["0.5.0", "pyproject"])
@pytest.mark.parametrize("example_name", ["0.5.0", "pyproject", "table_names"])
def test_parsed_document_are_properly_json_representable(
example, json_example, example_name
):
Expand Down
71 changes: 61 additions & 10 deletions tomlkit/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ def _split_table_name(self, name): # type: (str) -> Generator[Key]
in_name = False
current = ""
t = KeyType.Bare
for c in name:
parts = 0
for c in name.strip():
c = TOMLChar(c)

if c == ".":
Expand All @@ -212,7 +213,8 @@ def _split_table_name(self, name): # type: (str) -> Generator[Key]
if not current:
raise self.parse_error()

yield Key(current, t=t, sep="")
yield Key(current.strip(), t=t, sep="")
parts += 1

current = ""
t = KeyType.Bare
Expand All @@ -233,17 +235,35 @@ def _split_table_name(self, name): # type: (str) -> Generator[Key]

in_name = False
else:
if current and TOMLChar(current[-1]).is_spaces() and not parts:
raise self.parse_error()

in_name = True
t = KeyType.Literal if c == "'" else KeyType.Basic

continue
elif in_name or c.is_bare_key_char():
if (
not in_name
and current
and TOMLChar(current[-1]).is_spaces()
and not parts
):
raise self.parse_error()

current += c
elif c.is_spaces():
# A space is only valid at this point
# if it's in between parts.
# We store it for now and will check
# later if it's valid
current += c
continue
else:
raise self.parse_error()

if current:
yield Key(current, t=t, sep="")
if current.strip():
yield Key(current.strip(), t=t, sep="")

def _parse_item(self): # type: () -> Optional[Tuple[Optional[Key], Item]]
"""
Expand Down Expand Up @@ -916,15 +936,46 @@ def _parse_table(

is_aot = True

# Key
# Consume any whitespace
self.mark()
while self._current != "]" and self.inc():
if self.end():
raise self.parse_error(UnexpectedEofError)

while self._current.is_spaces() and self.inc():
pass

name = self.extract()
ws_prefix = self.extract()

# Key
if self._current in [StringType.SLL.value, StringType.SLB.value]:
delimiter = (
StringType.SLL
if self._current == StringType.SLL.value
else StringType.SLB
)
name = self._parse_string(delimiter)
name = "{delimiter}{name}{delimiter}".format(
delimiter=delimiter.value, name=name
)

self.mark()
while self._current != "]" and self.inc():
if self.end():
raise self.parse_error(UnexpectedEofError)

pass

ws_suffix = self.extract()
name += ws_suffix
else:
self.mark()
while self._current != "]" and self.inc():
if self.end():
raise self.parse_error(UnexpectedEofError)

pass

name = self.extract()

name = ws_prefix + name

if not name.strip():
raise self.parse_error(EmptyTableNameError)

Expand Down

0 comments on commit c07e876

Please sign in to comment.