Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-tomlkit for openSUSE:Factory checked in at 2026-03-11 20:49:50 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-tomlkit (Old) and /work/SRC/openSUSE:Factory/.python-tomlkit.new.8177 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-tomlkit" Wed Mar 11 20:49:50 2026 rev:21 rq:1337914 version:0.14.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-tomlkit/python-tomlkit.changes 2025-09-12 21:12:00.681504853 +0200 +++ /work/SRC/openSUSE:Factory/.python-tomlkit.new.8177/python-tomlkit.changes 2026-03-11 20:49:58.832783361 +0100 @@ -1,0 +2,12 @@ +Tue Mar 10 08:36:34 UTC 2026 - Dirk Müller <[email protected]> + +- update to 0.14.0: + * Drop support for Python older than 3.9. Remove 3.8 from the + CI matrix. + * Custom encoders can now receive `_parent` and `_sort_keys` + parameters to enable proper encoding of nested structures. + * Add `String.type` property to get the string type. + * Fixed `tomlkit.boolean()` API to correctly handle boolean + inputs. + +------------------------------------------------------------------- Old: ---- tomlkit-0.13.3.tar.gz New: ---- tomlkit-0.14.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-tomlkit.spec ++++++ --- /var/tmp/diff_new_pack.ZhcEwV/_old 2026-03-11 20:49:59.536811904 +0100 +++ /var/tmp/diff_new_pack.ZhcEwV/_new 2026-03-11 20:49:59.540812066 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-tomlkit # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2026 SUSE LLC and contributors # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-tomlkit -Version: 0.13.3 +Version: 0.14.0 Release: 0 Summary: Style preserving TOML library License: MIT ++++++ tomlkit-0.13.3.tar.gz -> tomlkit-0.14.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/CHANGELOG.md new/tomlkit-0.14.0/CHANGELOG.md --- old/tomlkit-0.13.3/CHANGELOG.md 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/CHANGELOG.md 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,19 @@ # Change Log -## [Unreleased] +## [0.14.0] - 2026-01-13 + +### Changed + +- Drop support for Python older than 3.9. Remove 3.8 from the CI matrix. + +### Added + +- Custom encoders can now receive `_parent` and `_sort_keys` parameters to enable proper encoding of nested structures. ([#429](https://github.com/python-poetry/tomlkit/issues/429)) +- Add `String.type` property to get the string type. ([#443](https://github.com/python-poetry/tomlkit/issues/443)) + +## Fixed + +- Fixed `tomlkit.boolean()` API to correctly handle boolean inputs. ([#442](https://github.com/python-poetry/tomlkit/issues/442)) ## [0.13.3] - 2025-06-05 @@ -439,7 +452,8 @@ - Fixed handling of super tables with different sections. - Fixed raw strings escaping. -[unreleased]: https://github.com/sdispater/tomlkit/compare/0.13.3...master +[unreleased]: https://github.com/sdispater/tomlkit/compare/0.14.0...master +[0.14.0]: https://github.com/sdispater/tomlkit/releases/tag/0.14.0 [0.13.3]: https://github.com/sdispater/tomlkit/releases/tag/0.13.3 [0.13.2]: https://github.com/sdispater/tomlkit/releases/tag/0.13.2 [0.13.1]: https://github.com/sdispater/tomlkit/releases/tag/0.13.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/PKG-INFO new/tomlkit-0.14.0/PKG-INFO --- old/tomlkit-0.13.3/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100 @@ -1,19 +1,20 @@ -Metadata-Version: 2.3 +Metadata-Version: 2.4 Name: tomlkit -Version: 0.13.3 +Version: 0.14.0 Summary: Style preserving TOML library License: MIT +License-File: LICENSE Author: Sébastien Eustace Author-email: [email protected] -Requires-Python: >=3.8 +Requires-Python: >=3.9 Classifier: License :: OSI Approved :: MIT License Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 Classifier: Programming Language :: Python :: 3.10 Classifier: Programming Language :: Python :: 3.11 Classifier: Programming Language :: Python :: 3.12 Classifier: Programming Language :: Python :: 3.13 +Classifier: Programming Language :: Python :: 3.14 Project-URL: Homepage, https://github.com/sdispater/tomlkit Project-URL: Repository, https://github.com/sdispater/tomlkit Description-Content-Type: text/markdown diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/docs/requirements.txt new/tomlkit-0.14.0/docs/requirements.txt --- old/tomlkit-0.13.3/docs/requirements.txt 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/docs/requirements.txt 1970-01-01 01:00:00.000000000 +0100 @@ -18,7 +18,9 @@ # via requests imagesize==1.4.1 # via sphinx -jinja2==3.1.5 +importlib-metadata==8.7.0 + # via sphinx +jinja2==3.1.6 # via sphinx markupsafe==2.1.5 # via jinja2 @@ -28,7 +30,7 @@ # via # furo # sphinx -requests==2.32.3 +requests==2.32.4 # via sphinx snowballstemmer==2.2.0 # via sphinx @@ -53,5 +55,9 @@ # via sphinx sphinxcontrib-serializinghtml==1.1.10 # via sphinx -urllib3==2.2.2 +tomli==2.2.1 + # via sphinx +urllib3==2.5.0 # via requests +zipp==3.23.0 + # via importlib-metadata diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/pyproject.toml new/tomlkit-0.14.0/pyproject.toml --- old/tomlkit-0.13.3/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/pyproject.toml 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ [tool.poetry] name = "tomlkit" -version = "0.13.3" +version = "0.14.0" description = "Style preserving TOML library" authors = [ "Sébastien Eustace <[email protected]>", @@ -21,7 +21,7 @@ ] [tool.poetry.dependencies] -python = ">=3.8" +python = ">=3.9" [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tests/test_items.py new/tomlkit-0.14.0/tests/test_items.py --- old/tomlkit-0.13.3/tests/test_items.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tests/test_items.py 1970-01-01 01:00:00.000000000 +0100 @@ -121,7 +121,7 @@ d = item([{"a": "A"}, {"b": "B"}]) unwrapped = d.unwrap() assert_is_ppo(unwrapped, list) - for du, _ in zip(unwrapped, d): + for du, _ in zip(unwrapped, d): # noqa: B905 assert_is_ppo(du, dict) for ku in du: vu = du[ku] @@ -986,6 +986,120 @@ api.unregister_encoder(encode_decimal) +def test_custom_encoders_with_parent_and_sort_keys(): + """Test that custom encoders can receive _parent and _sort_keys parameters.""" + import decimal + + parent_captured = None + sort_keys_captured = None + + @api.register_encoder + def encode_decimal_with_context(obj, _parent=None, _sort_keys=False): + nonlocal parent_captured, sort_keys_captured + if isinstance(obj, decimal.Decimal): + parent_captured = _parent + sort_keys_captured = _sort_keys + return api.float_(str(obj)) + raise TypeError + + # Test with default parameters + result = api.item(decimal.Decimal("1.23")) + assert result.as_string() == "1.23" + assert parent_captured is None + assert sort_keys_captured is False + + # Test with custom parent and sort_keys + parent_captured = None + sort_keys_captured = None + table = api.table() + result = item(decimal.Decimal("4.56"), _parent=table, _sort_keys=True) + assert result.as_string() == "4.56" + assert parent_captured is table + assert sort_keys_captured is True + + api.unregister_encoder(encode_decimal_with_context) + + +def test_custom_encoders_backward_compatibility(): + """Test that old-style custom encoders still work without modification.""" + import decimal + + @api.register_encoder + def encode_decimal_old_style(obj): + # Old style encoder - only accepts obj parameter + if isinstance(obj, decimal.Decimal): + return api.float_(str(obj)) + raise TypeError + + # Should work exactly as before + result = api.item(decimal.Decimal("2.34")) + assert result.as_string() == "2.34" + + # Should work when called from item() with extra parameters + table = api.table() + result = item(decimal.Decimal("5.67"), _parent=table, _sort_keys=True) + assert result.as_string() == "5.67" + + api.unregister_encoder(encode_decimal_old_style) + + +def test_custom_encoders_with_kwargs(): + """Test that custom encoders can use **kwargs to accept additional parameters.""" + import decimal + + kwargs_captured = None + + @api.register_encoder + def encode_decimal_with_kwargs(obj, **kwargs): + nonlocal kwargs_captured + if isinstance(obj, decimal.Decimal): + kwargs_captured = kwargs + return api.float_(str(obj)) + raise TypeError + + # Test with parent and sort_keys passed as kwargs + table = api.table() + result = item(decimal.Decimal("7.89"), _parent=table, _sort_keys=True) + assert result.as_string() == "7.89" + assert kwargs_captured == {"_parent": table, "_sort_keys": True} + + api.unregister_encoder(encode_decimal_with_kwargs) + + +def test_custom_encoders_for_complex_objects(): + """Test custom encoders that need to encode nested structures.""" + + class CustomDict: + def __init__(self, data): + self.data = data + + @api.register_encoder + def encode_custom_dict(obj, _parent=None, _sort_keys=False): + if isinstance(obj, CustomDict): + # Create a table and use item() to convert nested values + table = api.table() + for key, value in obj.data.items(): + # Pass along _parent and _sort_keys when converting nested values + table[key] = item(value, _parent=table, _sort_keys=_sort_keys) + return table + raise TypeError + + # Test with nested structure + custom_obj = CustomDict({"a": 1, "b": {"c": 2, "d": 3}}) + result = item(custom_obj, _sort_keys=True) + + # Should properly format as a table with sorted keys + expected = """a = 1 + +[b] +c = 2 +d = 3 +""" + assert result.as_string() == expected + + api.unregister_encoder(encode_custom_dict) + + def test_no_extra_minus_sign(): doc = parse("a = -1") assert doc.as_string() == "a = -1" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tests/test_toml_document.py new/tomlkit-0.14.0/tests/test_toml_document.py --- old/tomlkit-0.13.3/tests/test_toml_document.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tests/test_toml_document.py 1970-01-01 01:00:00.000000000 +0100 @@ -1293,3 +1293,24 @@ "foo": {}, "bar": {}, } + + +def test_appending_to_super_table(): + content = """\ +[a.b] +value = 5 +""" + + doc = parse(content) + table_a = doc["a"] + table_a.append(tomlkit.key(["c", "d"]), "foo") + + expected = """\ +[a] +c.d = "foo" + +[a.b] +value = 5 +""" + + assert doc.as_string() == expected diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tomlkit/__init__.py new/tomlkit-0.14.0/tomlkit/__init__.py --- old/tomlkit-0.13.3/tomlkit/__init__.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tomlkit/__init__.py 1970-01-01 01:00:00.000000000 +0100 @@ -27,7 +27,7 @@ from tomlkit.api import ws -__version__ = "0.13.3" +__version__ = "0.14.0" __all__ = [ "TOMLDocument", "aot", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tomlkit/_utils.py new/tomlkit-0.14.0/tomlkit/_utils.py --- old/tomlkit-0.13.3/tomlkit/_utils.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tomlkit/_utils.py 1970-01-01 01:00:00.000000000 +0100 @@ -2,13 +2,13 @@ import re +from collections.abc import Collection from collections.abc import Mapping from datetime import date from datetime import datetime from datetime import time from datetime import timedelta from datetime import timezone -from typing import Collection from tomlkit._compat import decode diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tomlkit/api.py new/tomlkit-0.14.0/tomlkit/api.py --- old/tomlkit-0.13.3/tomlkit/api.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tomlkit/api.py 1970-01-01 01:00:00.000000000 +0100 @@ -3,9 +3,10 @@ import contextlib import datetime as _datetime +from collections.abc import Iterable from collections.abc import Mapping from typing import IO -from typing import Iterable +from typing import TYPE_CHECKING from typing import TypeVar from tomlkit._utils import parse_rfc3339 @@ -19,7 +20,6 @@ from tomlkit.items import Date from tomlkit.items import DateTime from tomlkit.items import DottedKey -from tomlkit.items import Encoder from tomlkit.items import Float from tomlkit.items import InlineTable from tomlkit.items import Integer @@ -37,6 +37,12 @@ from tomlkit.toml_document import TOMLDocument +if TYPE_CHECKING: + from tomlkit.items import Encoder + + E = TypeVar("E", bound=Encoder) + + def loads(string: str | bytes) -> TOMLDocument: """ Parses a string into a TOMLDocument. @@ -111,9 +117,9 @@ return item(float(raw)) -def boolean(raw: str) -> Bool: +def boolean(raw: str | bool) -> Bool: """Turn `true` or `false` into a boolean item.""" - return item(raw == "true") + return item(raw == "true" if isinstance(raw, str) else raw) def string( @@ -294,13 +300,22 @@ return Comment(Trivia(comment_ws=" ", comment="# " + string)) -E = TypeVar("E", bound=Encoder) - - def register_encoder(encoder: E) -> E: """Add a custom encoder, which should be a function that will be called - if the value can't otherwise be converted. It should takes a single value - and return a TOMLKit item or raise a ``ConvertError``. + if the value can't otherwise be converted. + + The encoder should return a TOMLKit item or raise a ``ConvertError``. + + Example: + @register_encoder + def encode_custom_dict(obj, _parent=None, _sort_keys=False): + if isinstance(obj, CustomDict): + tbl = table() + for key, value in obj.items(): + # Pass along parameters when encoding nested values + tbl[key] = item(value, _parent=tbl, _sort_keys=_sort_keys) + return tbl + raise ConvertError("Not a CustomDict") """ CUSTOM_ENCODERS.append(encoder) return encoder diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tomlkit/container.py new/tomlkit-0.14.0/tomlkit/container.py --- old/tomlkit-0.13.3/tomlkit/container.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tomlkit/container.py 1970-01-01 01:00:00.000000000 +0100 @@ -2,8 +2,8 @@ import copy +from collections.abc import Iterator from typing import Any -from typing import Iterator from tomlkit._compat import decode from tomlkit._types import _CustomDict @@ -521,12 +521,19 @@ if prefix is not None: _key = prefix + "." + _key - if not table.is_super_table() or ( - any( - not isinstance(v, (Table, AoT, Whitespace, Null)) - for _, v in table.value.body + if ( + not table.is_super_table() + or ( + any( + not isinstance(v, (Table, AoT, Whitespace, Null)) + for _, v in table.value.body + ) + and not key.is_dotted() + ) + or ( + any(k.is_dotted() for k, v in table.value.body if isinstance(v, Table)) + and not key.is_dotted() ) - and not key.is_dotted() ): open_, close = "[", "]" if table.is_aot_element(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tomlkit/exceptions.py new/tomlkit-0.14.0/tomlkit/exceptions.py --- old/tomlkit-0.13.3/tomlkit/exceptions.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tomlkit/exceptions.py 1970-01-01 01:00:00.000000000 +0100 @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Collection +from collections.abc import Collection class TOMLKitError(Exception): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomlkit-0.13.3/tomlkit/items.py new/tomlkit-0.14.0/tomlkit/items.py --- old/tomlkit-0.13.3/tomlkit/items.py 1970-01-01 01:00:00.000000000 +0100 +++ new/tomlkit-0.14.0/tomlkit/items.py 1970-01-01 01:00:00.000000000 +0100 @@ -3,11 +3,14 @@ import abc import copy import dataclasses -import math +import inspect import re import string -import sys +from collections.abc import Collection +from collections.abc import Iterable +from collections.abc import Iterator +from collections.abc import Sequence from datetime import date from datetime import datetime from datetime import time @@ -15,11 +18,6 @@ from enum import Enum from typing import TYPE_CHECKING from typing import Any -from typing import Callable -from typing import Collection -from typing import Iterable -from typing import Iterator -from typing import Sequence from typing import TypeVar from typing import cast from typing import overload @@ -38,11 +36,17 @@ if TYPE_CHECKING: + from typing import Protocol + from tomlkit import container + class Encoder(Protocol): + def __call__( + self, __value: Any, _parent: Item | None = None, _sort_keys: bool = False + ) -> Item: ... + ItemT = TypeVar("ItemT", bound="Item") -Encoder = Callable[[Any], "Item"] CUSTOM_ENCODERS: list[Encoder] = [] AT = TypeVar("AT", bound="AbstractTable") @@ -199,7 +203,16 @@ else: for encoder in CUSTOM_ENCODERS: try: - rv = encoder(value) + # Check if encoder accepts keyword arguments for backward compatibility + sig = inspect.signature(encoder) + if "_parent" in sig.parameters or any( + p.kind == p.VAR_KEYWORD for p in sig.parameters.values() + ): + # New style encoder that can accept additional parameters + rv = encoder(value, _parent=_parent, _sort_keys=_sort_keys) + else: + # Old style encoder that only accepts value + rv = encoder(value) except ConvertError: pass else: @@ -740,12 +753,8 @@ __truediv__ = wrap_method(float.__truediv__) __trunc__ = float.__trunc__ - if sys.version_info >= (3, 9): - __ceil__ = float.__ceil__ - __floor__ = float.__floor__ - else: - __ceil__ = math.ceil - __floor__ = math.floor + __ceil__ = float.__ceil__ + __floor__ = float.__floor__ class Bool(Item): @@ -1852,6 +1861,10 @@ def as_string(self) -> str: return f"{self._t.value}{decode(self._original)}{self._t.value}" + @property + def type(self) -> StringType: + return self._t + def __add__(self: ItemT, other: str) -> ItemT: if not isinstance(other, str): return NotImplemented
