Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-tomli for openSUSE:Factory checked in at 2026-03-30 18:30:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-tomli (Old) and /work/SRC/openSUSE:Factory/.python-tomli.new.1999 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-tomli" Mon Mar 30 18:30:06 2026 rev:12 rq:1343517 version:2.4.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-tomli/python-tomli.changes 2026-01-28 15:07:06.977926351 +0100 +++ /work/SRC/openSUSE:Factory/.python-tomli.new.1999/python-tomli.changes 2026-03-30 18:30:46.317755213 +0200 @@ -1,0 +2,7 @@ +Sun Mar 29 19:02:30 UTC 2026 - Dirk Müller <[email protected]> + +- update to 2.4.1: + * Limit number of parts of a TOML key to address quadratic time + complexity + +------------------------------------------------------------------- Old: ---- tomli-2.4.0.tar.gz New: ---- tomli-2.4.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-tomli.spec ++++++ --- /var/tmp/diff_new_pack.Wc8Xgs/_old 2026-03-30 18:30:47.313796610 +0200 +++ /var/tmp/diff_new_pack.Wc8Xgs/_new 2026-03-30 18:30:47.317796776 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-tomli -Version: 2.4.0 +Version: 2.4.1 Release: 0 Summary: A lil' TOML parser License: MIT @@ -30,10 +30,9 @@ # Avoid build cycles # https://flit.readthedocs.io/en/latest/bootstrap.html #!BuildIgnore: python3-tomli -#!BuildIgnore: python36-tomli -#!BuildIgnore: python38-tomli -#!BuildIgnore: python39-tomli -#!BuildIgnore: python310-tomli +#!BuildIgnore: python311-tomli +#!BuildIgnore: python313-tomli +#!BuildIgnore: python314-tomli #!BuildIgnore: ca-certificates BuildRequires: fdupes BuildRequires: python-rpm-macros ++++++ tomli-2.4.0.tar.gz -> tomli-2.4.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/.bumpversion.cfg new/tomli-2.4.1/.bumpversion.cfg --- old/tomli-2.4.0/.bumpversion.cfg 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/.bumpversion.cfg 2026-03-25 21:11:29.000000000 +0100 @@ -2,7 +2,7 @@ commit = True tag = True tag_name = {new_version} -current_version = 2.4.0 +current_version = 2.4.1 [bumpversion:file:pyproject.toml] search = version = "{current_version}" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/.pre-commit-config.yaml new/tomli-2.4.1/.pre-commit-config.yaml --- old/tomli-2.4.0/.pre-commit-config.yaml 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/.pre-commit-config.yaml 2026-03-25 21:11:29.000000000 +0100 @@ -1,6 +1,6 @@ repos: - repo: https://github.com/Lucas-C/pre-commit-hooks - rev: a30f0d816e5062a67d87c8de753cfe499672b959 # frozen: v1.5.5 + rev: ad1b27d73581aa16cca06fc4a0761fc563ffe8e8 # frozen: v1.5.6 hooks: - id: insert-license files: '^src/.+\.py$|^tests/.+\.py$' @@ -28,11 +28,11 @@ files: '^src/.+\.py$' args: ['--never', '--application-directories', 'src'] - repo: https://github.com/PyCQA/isort - rev: 0a09c783808cfe77bb3269250f663ff733d23302 # frozen: 7.0.0 + rev: 3459bdee0962449aad91235273c3fd1306dfebe5 # frozen: 8.0.0 hooks: - id: isort - repo: https://github.com/psf/black-pre-commit-mirror - rev: 831207fd435b47aeffdf6af853097e64322b4d44 # frozen: 25.12.0 + rev: ea488cebbfd88a5f50b8bd95d5c829d0bb76feb8 # frozen: 26.1.0 hooks: - id: black - repo: https://github.com/pre-commit/pre-commit-hooks diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/CHANGELOG.md new/tomli-2.4.1/CHANGELOG.md --- old/tomli-2.4.0/CHANGELOG.md 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/CHANGELOG.md 2026-03-25 21:11:29.000000000 +0100 @@ -1,5 +1,15 @@ # Changelog +## 2.3.1 + +- Fixed + - Backport: Limit number of parts of a TOML key to address quadratic time complexity + +## 2.4.1 + +- Fixed + - Limit number of parts of a TOML key to address quadratic time complexity + ## 2.4.0 - Added diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/README.md new/tomli-2.4.1/README.md --- old/tomli-2.4.0/README.md 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/README.md 2026-03-25 21:11:29.000000000 +0100 @@ -24,8 +24,8 @@ - [Is there a `dumps`, `write` or `encode` function?](#is-there-a-dumps-write-or-encode-function) - [How do TOML types map into Python types?](#how-do-toml-types-map-into-python-types) - [Performance](#performance) - - [Pure Python](#pure-python) - [Mypyc generated wheel](#mypyc-generated-wheel) + - [Pure Python](#pure-python) <!-- mdformat-toc end --> @@ -156,7 +156,7 @@ - it's lil' - pure Python with zero dependencies - the fastest pure Python parser [\*](#pure-python): - 18x as fast as [tomlkit](https://pypi.org/project/tomlkit/), + 14x as fast as [tomlkit](https://pypi.org/project/tomlkit/), 2.1x as fast as [toml](https://pypi.org/project/toml/) - outputs [basic data types](#how-do-toml-types-map-into-python-types) only - 100% spec compliant: passes all tests in @@ -202,36 +202,32 @@ The `benchmark/` folder in this repository contains a performance benchmark for comparing the various Python TOML parsers. -Below are the results for commit [0724e2a](https://github.com/hukkin/tomli/tree/0724e2ab1858da7f5e05a9bffdb24c33589d951c). +Below are the results for commit [064e492](https://github.com/hukkin/tomli/tree/064e492919b2338def788753b8c981c9131334c0). -### Pure Python<a name="pure-python"></a> +### Mypyc generated wheel<a name="mypyc-generated-wheel"></a> ```console foo@bar:~/dev/tomli$ python --version -Python 3.12.7 +Python 3.14.2 foo@bar:~/dev/tomli$ pip freeze -attrs==21.4.0 -click==8.1.7 -pytomlpp==1.0.13 -qtoml==0.3.1 -rtoml==0.11.0 +pytomlpp==1.1.0 +rtoml==0.13.0 toml==0.10.2 tomli @ file:///home/foo/dev/tomli -tomlkit==0.13.2 +tomlkit==0.13.3 foo@bar:~/dev/tomli$ python benchmark/run.py Parsing data.toml 5000 times: ------------------------------------------------------ parser | exec time | performance (more is better) -----------+------------+----------------------------- - rtoml | 0.647 s | baseline (100%) - pytomlpp | 0.891 s | 72.62% - tomli | 3.14 s | 20.56% - toml | 6.69 s | 9.67% - qtoml | 8.27 s | 7.82% - tomlkit | 56.1 s | 1.15% + rtoml | 0.328 s | baseline (100%) + pytomlpp | 0.365 s | 89.75% + tomli | 0.838 s | 39.12% + toml | 3.01 s | 10.90% + tomlkit | 20.7 s | 1.59% ``` -### Mypyc generated wheel<a name="mypyc-generated-wheel"></a> +### Pure Python<a name="pure-python"></a> ```console foo@bar:~/dev/tomli$ python benchmark/run.py @@ -239,10 +235,9 @@ ------------------------------------------------------ parser | exec time | performance (more is better) -----------+------------+----------------------------- - rtoml | 0.668 s | baseline (100%) - pytomlpp | 0.893 s | 74.81% - tomli | 1.96 s | 34.18% - toml | 6.64 s | 10.07% - qtoml | 8.26 s | 8.09% - tomlkit | 52.9 s | 1.26% + rtoml | 0.323 s | baseline (100%) + pytomlpp | 0.365 s | 88.40% + tomli | 1.44 s | 22.36% + toml | 3.03 s | 10.65% + tomlkit | 20.6 s | 1.57% ``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/benchmark/requirements.txt new/tomli-2.4.1/benchmark/requirements.txt --- old/tomli-2.4.0/benchmark/requirements.txt 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/benchmark/requirements.txt 2026-03-25 21:11:29.000000000 +0100 @@ -5,5 +5,4 @@ pytomlpp toml tomlkit -qtoml rtoml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/benchmark/run.py new/tomli-2.4.1/benchmark/run.py --- old/tomli-2.4.0/benchmark/run.py 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/benchmark/run.py 2026-03-25 21:11:29.000000000 +0100 @@ -5,7 +5,6 @@ import timeit import pytomlpp -import qtoml import rtoml import toml import tomlkit @@ -22,7 +21,7 @@ ) -> float: placeholder = "Running..." print(f"{name:>{col_width[0]}} | {placeholder}", end="", flush=True) - time_taken = timeit.timeit(func, number=run_count) + time_taken = min(timeit.repeat(func, number=run_count, repeat=5)) print("\b" * len(placeholder), end="") time_suffix = " s" print(f"{time_taken:{col_width[1]-len(time_suffix)}.3g}{time_suffix}", end="") @@ -39,9 +38,6 @@ data_path = Path(__file__).parent / "data.toml" test_data = data_path.read_bytes().decode() - # qtoml has a bug making it crash without this newline normalization - test_data = test_data.replace("\r\n", "\n") - col_width = (10, 10, 28) col_head = ("parser", "exec time", "performance (more is better)") print(f"Parsing data.toml {run_count} times:") @@ -55,7 +51,6 @@ benchmark("pytomlpp", run_count, lambda: pytomlpp.loads(test_data), col_width, compare_to=baseline) # noqa: E501 benchmark("tomli", run_count, lambda: tomli.loads(test_data), col_width, compare_to=baseline) # noqa: E501 benchmark("toml", run_count, lambda: toml.loads(test_data), col_width, compare_to=baseline) # noqa: E501 - benchmark("qtoml", run_count, lambda: qtoml.loads(test_data), col_width, compare_to=baseline) # noqa: E501 benchmark("tomlkit", run_count, lambda: tomlkit.parse(test_data), col_width, compare_to=baseline) # noqa: E501 # fmt: on diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/pyproject.toml new/tomli-2.4.1/pyproject.toml --- old/tomli-2.4.0/pyproject.toml 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/pyproject.toml 2026-03-25 21:11:29.000000000 +0100 @@ -4,7 +4,7 @@ [project] name = "tomli" -version = "2.4.0" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT +version = "2.4.1" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT description = "A lil' TOML parser" authors = [ { name = "Taneli Hukkinen", email = "[email protected]" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/scripts/mypyc_tox new/tomli-2.4.1/scripts/mypyc_tox --- old/tomli-2.4.0/scripts/mypyc_tox 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/scripts/mypyc_tox 2026-03-25 21:11:29.000000000 +0100 @@ -9,6 +9,7 @@ sets the `TOMLI_USE_MYPYC=1` environment variable that setup.py reads to enable mypyc. """ + import os from pathlib import Path import shutil diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/src/tomli/__init__.py new/tomli-2.4.1/src/tomli/__init__.py --- old/tomli-2.4.0/src/tomli/__init__.py 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/src/tomli/__init__.py 2026-03-25 21:11:29.000000000 +0100 @@ -3,6 +3,6 @@ # Licensed to PSF under a Contributor Agreement. __all__ = ("loads", "load", "TOMLDecodeError") -__version__ = "2.4.0" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT +__version__ = "2.4.1" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY DO IT from ._parser import TOMLDecodeError, load, loads diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/src/tomli/_parser.py new/tomli-2.4.1/src/tomli/_parser.py --- old/tomli-2.4.0/src/tomli/_parser.py 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/src/tomli/_parser.py 2026-03-25 21:11:29.000000000 +0100 @@ -34,6 +34,13 @@ # lower number than where mypyc binaries crash. MAX_INLINE_NESTING: Final = sys.getrecursionlimit() +# Pathologically excessive number of parts in a key runs into quadratic +# behavior (e.g. in Flags.is_). +# Even if keys aren't currently parsed using recursion, they name a +# recursive structure, so it makes sense to limit it using getrecursionlimit() +# and RecursionError. +MAX_KEY_PARTS: Final = sys.getrecursionlimit() + ASCII_CTRL: Final = frozenset(chr(i) for i in range(32)) | frozenset(chr(127)) # Neither of these sets include quotation mark or backslash. They are @@ -475,6 +482,10 @@ pos = skip_chars(src, pos, TOML_WS) pos, key_part = parse_key_part(src, pos) key += (key_part,) + if len(key) > MAX_KEY_PARTS: + raise RecursionError( + f"TOML key has more than the allowed {MAX_KEY_PARTS} parts" + ) pos = skip_chars(src, pos, TOML_WS) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/tests/test_misc.py new/tomli-2.4.1/tests/test_misc.py --- old/tomli-2.4.0/tests/test_misc.py 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/tests/test_misc.py 2026-03-25 21:11:29.000000000 +0100 @@ -130,6 +130,23 @@ ): tomllib.loads(recursive_table_toml) + def test_key_recursion_limit(self): + nest_count = 310 + nested_key_toml = "a." * nest_count + "a = 1" + tomllib.loads(nested_key_toml) + + nest_count = sys.getrecursionlimit() - 2 + nested_key_toml = "a." * nest_count + "a = 1" + tomllib.loads(nested_key_toml) + + nest_count = sys.getrecursionlimit() + 2 + nested_key_toml = "a." * nest_count + "a = 1" + with self.assertRaisesRegex( + RecursionError, + r"TOML key has more than the allowed [0-9]+ parts", + ): + tomllib.loads(nested_key_toml) + def test_types_import(self): """Test that `_types` module runs. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/tomli-2.4.0/tomllib.md new/tomli-2.4.1/tomllib.md --- old/tomli-2.4.0/tomllib.md 2026-01-11 12:08:32.000000000 +0100 +++ new/tomli-2.4.1/tomllib.md 2026-03-25 21:11:29.000000000 +0100 @@ -35,7 +35,6 @@ from . import load_tests - unittest.main() ```
