diff --git a/docs/quickstart.rst b/docs/quickstart.rst index 6e80668..a3ce827 100644 --- a/docs/quickstart.rst +++ b/docs/quickstart.rst @@ -64,7 +64,7 @@ TOML Kit provides an intuitive API to modify TOML documents:: """ # Remove the newly added table - >>> doc.remove("table2") + >>> doc.pop("table2") # del doc["table2] is also possible Writing diff --git a/tests/test_toml_document.py b/tests/test_toml_document.py index f2e57c9..f5a5e8c 100644 --- a/tests/test_toml_document.py +++ b/tests/test_toml_document.py @@ -14,10 +14,8 @@ from tomlkit._utils import _utc from tomlkit.api import document from tomlkit.exceptions import NonExistentKey -from tomlkit.toml_document import TOMLDocument from .util import assert_is_ppo -from .util import elementary_test def test_document_is_a_dict(example): @@ -654,6 +652,31 @@ def test_string_output_order_is_preserved_for_out_of_order_tables(): assert expected == doc.as_string() +def test_remove_from_out_of_order_table(): + content = """[a] +x = 1 + +[c] +z = 3 + +[a.b] +y = 2 +""" + document = parse(content) + del document["a"]["b"] + assert ( + document.as_string() + == """[a] +x = 1 + +[c] +z = 3 + +""" + ) + assert json.dumps(document) == '{"a": {"x": 1}, "c": {"z": 3}}' + + def test_updating_nested_value_keeps_correct_indent(): content = """ [Key1] diff --git a/tomlkit/container.py b/tomlkit/container.py index 791b444..070c583 100644 --- a/tomlkit/container.py +++ b/tomlkit/container.py @@ -346,6 +346,25 @@ def append(self, key: Union[Key, str, None], item: Item) -> "Container": return self + def _remove_at(self, idx: int) -> None: + key = self._body[idx][0] + index = self._map.get(key) + if index is None: + raise NonExistentKey(key) + self._body[idx] = (None, Null()) + + if isinstance(index, tuple): + index = list(index) + index.remove(idx) + if len(index) == 1: + index = index.pop() + else: + index = tuple(index) + self._map[key] = index + else: + dict.__delitem__(self, key.key) + self._map.pop(key) + def remove(self, key: Union[Key, str]) -> "Container": """Remove a key from the container.""" if not isinstance(key, Key): @@ -804,7 +823,7 @@ def __init__(self, container: Container, indices: Tuple[int]) -> None: self._tables_map = {} for i in indices: - key, item = self._container._body[i] + _, item = self._container._body[i] if isinstance(item, Table): self._tables.append(item) @@ -842,10 +861,20 @@ def __setitem__(self, key: Union[Key, str], item: Any) -> None: if key is not None: dict.__setitem__(self, key, item) + def _remove_table(self, table: Table) -> None: + """Remove table from the parent container""" + self._tables.remove(table) + for idx, item in enumerate(self._container._body): + if item[1] is table: + self._container._remove_at(idx) + break + def __delitem__(self, key: Union[Key, str]) -> None: if key in self._tables_map: table = self._tables[self._tables_map[key]] del table[key] + if not table and len(self._tables) > 1: + self._remove_table(table) del self._tables_map[key] else: raise NonExistentKey(key) @@ -860,9 +889,6 @@ def __iter__(self) -> Iterator[str]: def __len__(self) -> int: return dict.__len__(self) - def __getattr__(self, attribute): - return getattr(self._internal_container, attribute) - def setdefault(self, key: Union[Key, str], default: Any) -> Any: super().setdefault(key, default=default) return self[key]