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 2022-02-03 23:15:58
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-tomli (Old)
 and      /work/SRC/openSUSE:Factory/.python-tomli.new.1898 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-tomli"

Thu Feb  3 23:15:58 2022 rev:3 rq:948285 version:2.0.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-tomli/python-tomli.changes        
2021-10-25 15:17:33.917680580 +0200
+++ /work/SRC/openSUSE:Factory/.python-tomli.new.1898/python-tomli.changes      
2022-02-03 23:16:23.460651870 +0100
@@ -1,0 +2,23 @@
+Thu Jan 20 20:10:07 UTC 2022 - Matej Cepl <mc...@suse.com>
+
+- Upgrade to 2.0.0:
+  - Removed Python 3.6 support
+  - Support for text file objects as load input. Use binary file
+    objects instead.
+  - First argument of load and loads can no longer be passed by
+    keyword.
+  - Allow lower case "t" and "z" in datetimes
+  - Raise an error when dotted keys define values outside the
+    "current table". Technically speaking TOML v1.0.0 does allow
+    such assignments but that isn't intended by specification
+    writers, and will change in a future specification version
+    (see the pull request).
+  - Illegal characters in error messages were surrounded by two
+    pairs of quotation marks
+  - TOMLDecodeError.__module__ is now the public import path
+    (tomli) instead of private import path (tomli._parser)
+  - Eliminated an import cycle when typing.TYPE_CHECKING is
+    True. This allows sphinx-autodoc-typehints to resolve type
+    annotations.
+
+-------------------------------------------------------------------

Old:
----
  tomli-1.2.1-gh.tar.gz

New:
----
  tomli-2.0.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-tomli.spec ++++++
--- /var/tmp/diff_new_pack.0SicVN/_old  2022-02-03 23:16:24.360645726 +0100
+++ /var/tmp/diff_new_pack.0SicVN/_new  2022-02-03 23:16:24.364645699 +0100
@@ -1,7 +1,7 @@
 #
 # spec file
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -27,13 +27,13 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-tomli%{psuffix}
-Version:        1.2.1
+Version:        2.0.0
 Release:        0
 Summary:        A lil' TOML parser
 License:        MIT
 URL:            https://github.com/hukkin/tomli
 # prefer github archive over pypi sdist for pacakged tests
-Source:         
https://github.com/hukkin/tomli/archive/refs/tags/%{version}.tar.gz#/tomli-%{version}-gh.tar.gz
+Source:         
https://github.com/hukkin/tomli/archive/refs/tags/%{version}.tar.gz#/tomli-%{version}.tar.gz
 BuildRequires:  %{python_module flit-core}
 BuildRequires:  %{python_module pip}
 # Avoid build cycles
@@ -58,7 +58,7 @@
 Tomli is a Python library for parsing TOML
 
 %prep
-%setup -q -n tomli-%{version}
+%autosetup -p1 -n tomli-%{version}
 
 %build
 export PYTHONPATH=$PWD

++++++ tomli-1.2.1-gh.tar.gz -> tomli-2.0.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/.bumpversion.cfg 
new/tomli-2.0.0/.bumpversion.cfg
--- old/tomli-1.2.1/.bumpversion.cfg    2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/.bumpversion.cfg    2021-12-13 22:09:35.000000000 +0100
@@ -2,7 +2,7 @@
 commit = True
 tag = True
 tag_name = {new_version}
-current_version = 1.2.1
+current_version = 2.0.0
 
 [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-1.2.1/.github/workflows/tests.yaml 
new/tomli-2.0.0/.github/workflows/tests.yaml
--- old/tomli-1.2.1/.github/workflows/tests.yaml        2021-08-05 
22:07:21.000000000 +0200
+++ new/tomli-2.0.0/.github/workflows/tests.yaml        2021-12-13 
22:09:35.000000000 +0100
@@ -32,9 +32,9 @@
     runs-on: ${{ matrix.os }}
     strategy:
       matrix:
-        python-version: ['pypy-3.6', 'pypy-3.7', '3.6', '3.7', '3.8', '3.9', 
'3.10-dev']
+        python-version: ['pypy-3.7', '3.7', '3.8', '3.9', '3.10', '3.11-dev']
         os: [ubuntu-latest, macos-latest, windows-latest]
-    continue-on-error: ${{ matrix.python-version == '3.10-dev' }}
+    continue-on-error: ${{ matrix.python-version == '3.11-dev' }}
 
     steps:
     - uses: actions/checkout@v2
@@ -50,11 +50,12 @@
 
     - name: Test with pytest
       run: |
-        pytest --cov --cov-fail-under=100
+        # Use 'python -m pytest' to add CWD to sys.path
+        python -m pytest --cov --cov-fail-under=100
 
     - name: Report coverage
-      if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.6'
-      uses: codecov/codecov-action@v1
+      if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.10'
+      uses: codecov/codecov-action@v2
 
   test-built-package:
     runs-on: ubuntu-latest
@@ -96,12 +97,16 @@
     - uses: actions/setup-python@v2
       with:
         python-version: '3.7'
-    - name: Install Flit
+    - name: Install build and publish tools
       run: |
-        pip install "flit==3.3.0"
-    - name: Build and publish
+        pip install build twine
+    - name: Build and check
       run: |
-        flit publish --no-setup-py
+        rm -rf dist/ && python -m build
+        twine check --strict dist/*
+    - name: Publish
+      run: |
+        twine upload dist/*
       env:
-        FLIT_USERNAME: __token__
-        FLIT_PASSWORD: ${{ secrets.PYPI_TOKEN }}
+        TWINE_USERNAME: __token__
+        TWINE_PASSWORD: ${{ secrets.PYPI_TOKEN }}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/.pre-commit-config.yaml 
new/tomli-2.0.0/.pre-commit-config.yaml
--- old/tomli-1.2.1/.pre-commit-config.yaml     2021-08-05 22:07:21.000000000 
+0200
+++ new/tomli-2.0.0/.pre-commit-config.yaml     2021-12-13 22:09:35.000000000 
+0100
@@ -1,6 +1,6 @@
 repos:
 - repo: https://github.com/executablebooks/mdformat
-  rev: b9b885e183ca16670b6d4a5ef8058664395dec58  # frozen: 0.7.7
+  rev: 427df9181bd4d8e65c1108b912ad47a81628f03b  # frozen: 0.7.10
   hooks:
   - id: mdformat
     additional_dependencies:
@@ -16,11 +16,11 @@
     - flake8-builtins
     - flake8-comprehensions
 - repo: https://github.com/PyCQA/isort
-  rev: 6e4281f018ff848226d8993596765b2285e1624f  # frozen: 5.9.2
+  rev: fd5ba70665a37ec301a1f714ed09336048b3be63  # frozen: 5.9.3
   hooks:
   - id: isort
 - repo: https://github.com/psf/black
-  rev: e3000ace2fd1fcb1c181bb7a8285f1f976bcbdc7  # frozen: 21.7b0
+  rev: 911470a610e47d9da5ea938b0887c3df62819b85  # frozen: 21.9b0
   hooks:
   - id: black
 - repo: https://github.com/myint/docformatter
@@ -38,7 +38,7 @@
   - id: python-check-blanket-noqa
   - id: python-check-blanket-type-ignore
 - repo: https://github.com/PyCQA/flake8
-  rev: dcd740bc0ebaf2b3d43e59a0060d157c97de13f3  # frozen: 3.9.2
+  rev: cbeb4c9c4137cff1568659fcc48e8b85cddd0c8d  # frozen: 4.0.1
   hooks:
   - id: flake8
     additional_dependencies:
@@ -46,7 +46,7 @@
     - flake8-builtins
     - flake8-comprehensions
 - repo: https://github.com/pre-commit/mirrors-mypy
-  rev: 44afb68a9695d04030edc5cdc5a4fc4f17e4f9e2  # frozen: v0.910
+  rev: 5cf22ccb774a8be8f47dfe4c1e8c4f177c608cbf  # frozen: v0.910-1
   hooks:
   - id: mypy
     args: ["--scripts-are-modules"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/CHANGELOG.md new/tomli-2.0.0/CHANGELOG.md
--- old/tomli-1.2.1/CHANGELOG.md        2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/CHANGELOG.md        2021-12-13 22:09:35.000000000 +0100
@@ -1,5 +1,28 @@
 # Changelog
 
+## 2.0.0
+
+- Removed
+  - Python 3.6 support
+  - Support for text file objects as `load` input. Use binary file objects 
instead.
+  - First argument of `load` and `loads` can no longer be passed by keyword.
+- Fixed
+  - Allow lower case "t" and "z" in datetimes
+- Improved
+  - Raise an error when dotted keys define values outside the "current table".
+    Technically speaking TOML v1.0.0 does allow such assignments
+    but that isn't intended by specification writers,
+    and will change in a future specification version (see the [pull 
request](https://github.com/toml-lang/toml/pull/848)).
+
+## 1.2.2
+
+- Fixed
+  - Illegal characters in error messages were surrounded by two pairs of 
quotation marks
+- Improved
+  - `TOMLDecodeError.__module__` is now the public import path (`tomli`) 
instead of private import path (`tomli._parser`)
+  - Eliminated an import cycle when `typing.TYPE_CHECKING` is `True`.
+    This allows `sphinx-autodoc-typehints` to resolve type annotations.
+
 ## 1.2.1
 
 - Fixed
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/README.md new/tomli-2.0.0/README.md
--- old/tomli-1.2.1/README.md   2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/README.md   2021-12-13 22:09:35.000000000 +0100
@@ -67,7 +67,6 @@
 The file must be opened in binary mode (with the `"rb"` flag).
 Binary mode will enforce decoding the file as UTF-8 with universal newlines 
disabled,
 both of which are required to correctly parse TOML.
-Support for text file objects is deprecated for removal in the next major 
release.
 
 ### Handle invalid TOML<a name="handle-invalid-toml"></a>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/pyproject.toml 
new/tomli-2.0.0/pyproject.toml
--- old/tomli-1.2.1/pyproject.toml      2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/pyproject.toml      2021-12-13 22:09:35.000000000 +0100
@@ -4,13 +4,13 @@
 
 [project]
 name = "tomli"
-version = "1.2.1"  # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY 
DO IT
+version = "2.0.0"  # DO NOT EDIT THIS LINE MANUALLY. LET bump2version UTILITY 
DO IT
 description = "A lil' TOML parser"
 authors = [
     { name = "Taneli Hukkinen", email = "huk...@users.noreply.github.com" },
 ]
 license = { file = "LICENSE" }
-requires-python = ">=3.6"
+requires-python = ">=3.7"
 readme = "README.md"
 classifiers = [
     "License :: OSI Approved :: MIT License",
@@ -18,7 +18,6 @@
     "Operating System :: Microsoft :: Windows",
     "Operating System :: POSIX :: Linux",
     "Programming Language :: Python :: 3 :: Only",
-    "Programming Language :: Python :: 3.6",
     "Programming Language :: Python :: 3.7",
     "Programming Language :: Python :: 3.8",
     "Programming Language :: Python :: 3.9",
@@ -35,16 +34,6 @@
 "Changelog" = "https://github.com/hukkin/tomli/blob/master/CHANGELOG.md";
 
 
-[tool.flit.sdist]
-exclude = [
-    "tests/",
-    "benchmark/",
-    "fuzzer/",
-    ".*",
-    "CHANGELOG.md",
-]
-
-
 [tool.isort]
 # Force imports to be sorted by module, independent of import type
 force_sort_within_sections = true
@@ -67,17 +56,18 @@
 legacy_tox_ini = '''
 [tox]
 # Only run pytest envs when no args given to tox
-envlist = py{36,37,38,39}
+envlist = py{37,38,39,310}
 isolated_build = True
 
-[testenv:py{36,37,38,39}]
+[testenv:py{37,38,39,310}]
 description = run tests against unpackaged source
 skip_install = True
 deps = -r tests/requirements.txt
 commands =
-    pytest {posargs}
+    # Use 'python -m pytest' to add CWD to sys.path
+    python -m pytest {posargs}
 
-[testenv:py{36,37,38,39}-package]
+[testenv:py{37,38,39,310}-package]
 description = run tests against a built package (can fail, in theory, if test 
dependencies need a tomli version incompatible with local state)
 deps = -r tests/requirements.txt
 commands =
@@ -139,15 +129,15 @@
 
 [tool.coverage.run]
 branch = true
-omit = ["tests/*", "*/site-packages/*"]
+source = ['tomli']
 
 [tool.coverage.report]
 # Regexes for lines to exclude from consideration
 exclude_lines = [
-    # Have to re-enable the standard pragma
-    "pragma: no cover",
+    # Re-enable the standard pragma (with extra strictness)
+    '# pragma: no cover\b',
     # Code for static type checkers
-    "if TYPE_CHECKING:",
+    'if TYPE_CHECKING:',
     # Scripts
     'if __name__ == .__main__.:',
 ]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tomli-1.2.1/tests/data/extras/invalid/dotted-keys/extend-defined-aot.toml 
new/tomli-2.0.0/tests/data/extras/invalid/dotted-keys/extend-defined-aot.toml
--- 
old/tomli-1.2.1/tests/data/extras/invalid/dotted-keys/extend-defined-aot.toml   
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/tomli-2.0.0/tests/data/extras/invalid/dotted-keys/extend-defined-aot.toml   
    2021-12-13 22:09:35.000000000 +0100
@@ -0,0 +1,3 @@
+[[tab.arr]]
+[tab]
+arr.val1=1
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tomli-1.2.1/tests/data/extras/invalid/dotted-keys/extend-defined-table-with-subtable.toml
 
new/tomli-2.0.0/tests/data/extras/invalid/dotted-keys/extend-defined-table-with-subtable.toml
--- 
old/tomli-1.2.1/tests/data/extras/invalid/dotted-keys/extend-defined-table-with-subtable.toml
       1970-01-01 01:00:00.000000000 +0100
+++ 
new/tomli-2.0.0/tests/data/extras/invalid/dotted-keys/extend-defined-table-with-subtable.toml
       2021-12-13 22:09:35.000000000 +0100
@@ -0,0 +1,4 @@
+[a.b.c.d]
+  z = 9
+[a]
+  b.c.d.k.t = 8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/tomli-1.2.1/tests/data/extras/invalid/dotted-keys/extend-defined-table.toml 
new/tomli-2.0.0/tests/data/extras/invalid/dotted-keys/extend-defined-table.toml
--- 
old/tomli-1.2.1/tests/data/extras/invalid/dotted-keys/extend-defined-table.toml 
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/tomli-2.0.0/tests/data/extras/invalid/dotted-keys/extend-defined-table.toml 
    2021-12-13 22:09:35.000000000 +0100
@@ -0,0 +1,4 @@
+[a.b.c]
+  z = 9
+[a]
+  b.c.t = 9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tests/requirements.txt 
new/tomli-2.0.0/tests/requirements.txt
--- old/tomli-1.2.1/tests/requirements.txt      2021-08-05 22:07:21.000000000 
+0200
+++ new/tomli-2.0.0/tests/requirements.txt      2021-12-13 22:09:35.000000000 
+0100
@@ -2,3 +2,4 @@
 pytest-randomly
 pytest-cov >=2.12.1
 python-dateutil
+coverage !=6.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tests/test_error.py 
new/tomli-2.0.0/tests/test_error.py
--- old/tomli-1.2.1/tests/test_error.py 2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/tests/test_error.py 2021-12-13 22:09:35.000000000 +0100
@@ -25,3 +25,13 @@
     with pytest.raises(tomli.TOMLDecodeError) as exc_info:
         tomli.loads("\n\nfwfw=")
     assert str(exc_info.value) == "Invalid value (at end of document)"
+
+
+def test_invalid_char_quotes():
+    with pytest.raises(tomli.TOMLDecodeError) as exc_info:
+        tomli.loads("v = '\n'")
+    assert " '\\n' " in str(exc_info.value)
+
+
+def test_module_name():
+    assert tomli.TOMLDecodeError().__module__ == "tomli"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tests/test_flags.py 
new/tomli-2.0.0/tests/test_flags.py
--- old/tomli-1.2.1/tests/test_flags.py 2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/tests/test_flags.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,13 +0,0 @@
-from tomli._parser import Flags
-
-
-def test_set_for_relative_key():
-    flags = Flags()
-    head_key = ("a", "b")
-    rel_key = ("c", "d")
-    flags.set_for_relative_key(head_key, rel_key, Flags.EXPLICIT_NEST)
-    assert not flags.is_(("a",), flags.EXPLICIT_NEST)
-    assert not flags.is_(("a", "b"), flags.EXPLICIT_NEST)
-    assert flags.is_(("a", "b", "c"), flags.EXPLICIT_NEST)
-    assert flags.is_(("a", "b", "c", "d"), flags.EXPLICIT_NEST)
-    assert not flags.is_(("a", "b", "c", "d", "e"), flags.EXPLICIT_NEST)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tests/test_misc.py 
new/tomli-2.0.0/tests/test_misc.py
--- old/tomli-1.2.1/tests/test_misc.py  2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/tests/test_misc.py  2021-12-13 22:09:35.000000000 +0100
@@ -12,12 +12,6 @@
     file_path = tmp_path / "test.toml"
     file_path.write_text(content)
 
-    # Test text mode
-    with open(file_path, encoding="utf-8", newline="") as f:
-        actual = tomli.load(f)  # type: ignore[arg-type]
-    assert actual == expected
-
-    # Test binary mode
     with open(file_path, "rb") as bin_f:
         actual = tomli.load(bin_f)
     assert actual == expected
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tomli/__init__.py 
new/tomli-2.0.0/tomli/__init__.py
--- old/tomli-1.2.1/tomli/__init__.py   2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/tomli/__init__.py   2021-12-13 22:09:35.000000000 +0100
@@ -1,6 +1,9 @@
 """A lil' TOML parser."""
 
 __all__ = ("loads", "load", "TOMLDecodeError")
-__version__ = "1.2.1"  # DO NOT EDIT THIS LINE MANUALLY. LET bump2version 
UTILITY DO IT
+__version__ = "2.0.0"  # DO NOT EDIT THIS LINE MANUALLY. LET bump2version 
UTILITY DO IT
 
 from tomli._parser import TOMLDecodeError, load, loads
+
+# Pretend this exception was created here.
+TOMLDecodeError.__module__ = __name__
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tomli/_parser.py 
new/tomli-2.0.0/tomli/_parser.py
--- old/tomli-1.2.1/tomli/_parser.py    2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/tomli/_parser.py    2021-12-13 22:09:35.000000000 +0100
@@ -1,17 +1,9 @@
+from __future__ import annotations
+
+from collections.abc import Iterable
 import string
 from types import MappingProxyType
-from typing import (
-    Any,
-    BinaryIO,
-    Callable,
-    Dict,
-    FrozenSet,
-    Iterable,
-    NamedTuple,
-    Optional,
-    Tuple,
-)
-import warnings
+from typing import Any, BinaryIO, NamedTuple
 
 from tomli._re import (
     RE_DATETIME,
@@ -21,6 +13,7 @@
     match_to_localtime,
     match_to_number,
 )
+from tomli._types import Key, ParseFloat, Pos
 
 ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
 
@@ -52,37 +45,23 @@
     }
 )
 
-# Type annotations
-ParseFloat = Callable[[str], Any]
-Key = Tuple[str, ...]
-Pos = int
-
 
 class TOMLDecodeError(ValueError):
     """An error raised if a document is not valid TOML."""
 
 
-def load(fp: BinaryIO, *, parse_float: ParseFloat = float) -> Dict[str, Any]:
+def load(__fp: BinaryIO, *, parse_float: ParseFloat = float) -> dict[str, Any]:
     """Parse TOML from a binary file object."""
-    s_bytes = fp.read()
-    try:
-        s = s_bytes.decode()
-    except AttributeError:
-        warnings.warn(
-            "Text file object support is deprecated in favor of binary file 
objects."
-            ' Use `open("foo.toml", "rb")` to open the file in binary mode.',
-            DeprecationWarning,
-        )
-        s = s_bytes  # type: ignore[assignment]
+    s = __fp.read().decode()
     return loads(s, parse_float=parse_float)
 
 
-def loads(s: str, *, parse_float: ParseFloat = float) -> Dict[str, Any]:  # 
noqa: C901
+def loads(__s: str, *, parse_float: ParseFloat = float) -> dict[str, Any]:  # 
noqa: C901
     """Parse TOML from a string."""
 
     # The spec allows converting "\r\n" to "\n", even in string
     # literals. Let's do so to simplify parsing.
-    src = s.replace("\r\n", "\n")
+    src = __s.replace("\r\n", "\n")
     pos = 0
     out = Output(NestedDict(), Flags())
     header: Key = ()
@@ -113,9 +92,10 @@
             pos = skip_chars(src, pos, TOML_WS)
         elif char == "[":
             try:
-                second_char: Optional[str] = src[pos + 1]
+                second_char: str | None = src[pos + 1]
             except IndexError:
                 second_char = None
+            out.flags.finalize_pending()
             if second_char == "[":
                 pos, header = create_list_rule(src, pos, out)
             else:
@@ -151,7 +131,16 @@
     EXPLICIT_NEST = 1
 
     def __init__(self) -> None:
-        self._flags: Dict[str, dict] = {}
+        self._flags: dict[str, dict] = {}
+        self._pending_flags: set[tuple[Key, int]] = set()
+
+    def add_pending(self, key: Key, flag: int) -> None:
+        self._pending_flags.add((key, flag))
+
+    def finalize_pending(self) -> None:
+        for key, flag in self._pending_flags:
+            self.set(key, flag, recursive=False)
+        self._pending_flags.clear()
 
     def unset_all(self, key: Key) -> None:
         cont = self._flags
@@ -161,19 +150,6 @@
             cont = cont[k]["nested"]
         cont.pop(key[-1], None)
 
-    def set_for_relative_key(self, head_key: Key, rel_key: Key, flag: int) -> 
None:
-        cont = self._flags
-        for k in head_key:
-            if k not in cont:
-                cont[k] = {"flags": set(), "recursive_flags": set(), "nested": 
{}}
-            cont = cont[k]["nested"]
-        for k in rel_key:
-            if k in cont:
-                cont[k]["flags"].add(flag)
-            else:
-                cont[k] = {"flags": {flag}, "recursive_flags": set(), 
"nested": {}}
-            cont = cont[k]["nested"]
-
     def set(self, key: Key, flag: int, *, recursive: bool) -> None:  # noqa: 
A003
         cont = self._flags
         key_parent, key_stem = key[:-1], key[-1]
@@ -206,7 +182,7 @@
 class NestedDict:
     def __init__(self) -> None:
         # The parsed content of the TOML document
-        self.dict: Dict[str, Any] = {}
+        self.dict: dict[str, Any] = {}
 
     def get_or_create_nest(
         self,
@@ -257,7 +233,7 @@
     pos: Pos,
     expect: str,
     *,
-    error_on: FrozenSet[str],
+    error_on: frozenset[str],
     error_on_eof: bool,
 ) -> Pos:
     try:
@@ -265,18 +241,18 @@
     except ValueError:
         new_pos = len(src)
         if error_on_eof:
-            raise suffixed_err(src, new_pos, f'Expected "{expect!r}"')
+            raise suffixed_err(src, new_pos, f"Expected {expect!r}") from None
 
     if not error_on.isdisjoint(src[pos:new_pos]):
         while src[pos] not in error_on:
             pos += 1
-        raise suffixed_err(src, pos, f'Found invalid character "{src[pos]!r}"')
+        raise suffixed_err(src, pos, f"Found invalid character {src[pos]!r}")
     return new_pos
 
 
 def skip_comment(src: str, pos: Pos) -> Pos:
     try:
-        char: Optional[str] = src[pos]
+        char: str | None = src[pos]
     except IndexError:
         char = None
     if char == "#":
@@ -295,7 +271,7 @@
             return pos
 
 
-def create_dict_rule(src: str, pos: Pos, out: Output) -> Tuple[Pos, Key]:
+def create_dict_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]:
     pos += 1  # Skip "["
     pos = skip_chars(src, pos, TOML_WS)
     pos, key = parse_key(src, pos)
@@ -306,14 +282,14 @@
     try:
         out.data.get_or_create_nest(key)
     except KeyError:
-        raise suffixed_err(src, pos, "Can not overwrite a value")
+        raise suffixed_err(src, pos, "Can not overwrite a value") from None
 
     if not src.startswith("]", pos):
         raise suffixed_err(src, pos, 'Expected "]" at the end of a table 
declaration')
     return pos + 1, key
 
 
-def create_list_rule(src: str, pos: Pos, out: Output) -> Tuple[Pos, Key]:
+def create_list_rule(src: str, pos: Pos, out: Output) -> tuple[Pos, Key]:
     pos += 2  # Skip "[["
     pos = skip_chars(src, pos, TOML_WS)
     pos, key = parse_key(src, pos)
@@ -327,7 +303,7 @@
     try:
         out.data.append_nest_to_list(key)
     except KeyError:
-        raise suffixed_err(src, pos, "Can not overwrite a value")
+        raise suffixed_err(src, pos, "Can not overwrite a value") from None
 
     if not src.startswith("]]", pos):
         raise suffixed_err(src, pos, 'Expected "]]" at the end of an array 
declaration')
@@ -341,16 +317,24 @@
     key_parent, key_stem = key[:-1], key[-1]
     abs_key_parent = header + key_parent
 
+    relative_path_cont_keys = (header + key[:i] for i in range(1, len(key)))
+    for cont_key in relative_path_cont_keys:
+        # Check that dotted key syntax does not redefine an existing table
+        if out.flags.is_(cont_key, Flags.EXPLICIT_NEST):
+            raise suffixed_err(src, pos, f"Cannot redefine namespace 
{cont_key}")
+        # Containers in the relative path can't be opened with the table 
syntax or
+        # dotted key/value syntax in following table sections.
+        out.flags.add_pending(cont_key, Flags.EXPLICIT_NEST)
+
     if out.flags.is_(abs_key_parent, Flags.FROZEN):
         raise suffixed_err(
-            src, pos, f"Can not mutate immutable namespace {abs_key_parent}"
+            src, pos, f"Cannot mutate immutable namespace {abs_key_parent}"
         )
-    # Containers in the relative path can't be opened with the table syntax 
after this
-    out.flags.set_for_relative_key(header, key, Flags.EXPLICIT_NEST)
+
     try:
         nest = out.data.get_or_create_nest(abs_key_parent)
     except KeyError:
-        raise suffixed_err(src, pos, "Can not overwrite a value")
+        raise suffixed_err(src, pos, "Can not overwrite a value") from None
     if key_stem in nest:
         raise suffixed_err(src, pos, "Can not overwrite a value")
     # Mark inline table and array namespaces recursively immutable
@@ -362,10 +346,10 @@
 
 def parse_key_value_pair(
     src: str, pos: Pos, parse_float: ParseFloat
-) -> Tuple[Pos, Key, Any]:
+) -> tuple[Pos, Key, Any]:
     pos, key = parse_key(src, pos)
     try:
-        char: Optional[str] = src[pos]
+        char: str | None = src[pos]
     except IndexError:
         char = None
     if char != "=":
@@ -376,13 +360,13 @@
     return pos, key, value
 
 
-def parse_key(src: str, pos: Pos) -> Tuple[Pos, Key]:
+def parse_key(src: str, pos: Pos) -> tuple[Pos, Key]:
     pos, key_part = parse_key_part(src, pos)
     key: Key = (key_part,)
     pos = skip_chars(src, pos, TOML_WS)
     while True:
         try:
-            char: Optional[str] = src[pos]
+            char: str | None = src[pos]
         except IndexError:
             char = None
         if char != ".":
@@ -394,9 +378,9 @@
         pos = skip_chars(src, pos, TOML_WS)
 
 
-def parse_key_part(src: str, pos: Pos) -> Tuple[Pos, str]:
+def parse_key_part(src: str, pos: Pos) -> tuple[Pos, str]:
     try:
-        char: Optional[str] = src[pos]
+        char: str | None = src[pos]
     except IndexError:
         char = None
     if char in BARE_KEY_CHARS:
@@ -410,12 +394,12 @@
     raise suffixed_err(src, pos, "Invalid initial character for a key part")
 
 
-def parse_one_line_basic_str(src: str, pos: Pos) -> Tuple[Pos, str]:
+def parse_one_line_basic_str(src: str, pos: Pos) -> tuple[Pos, str]:
     pos += 1
     return parse_basic_str(src, pos, multiline=False)
 
 
-def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> Tuple[Pos, 
list]:
+def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> tuple[Pos, 
list]:
     pos += 1
     array: list = []
 
@@ -439,7 +423,7 @@
             return pos + 1, array
 
 
-def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) -> 
Tuple[Pos, dict]:
+def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) -> 
tuple[Pos, dict]:
     pos += 1
     nested_dict = NestedDict()
     flags = Flags()
@@ -455,9 +439,9 @@
         try:
             nest = nested_dict.get_or_create_nest(key_parent, 
access_lists=False)
         except KeyError:
-            raise suffixed_err(src, pos, "Can not overwrite a value")
+            raise suffixed_err(src, pos, "Can not overwrite a value") from None
         if key_stem in nest:
-            raise suffixed_err(src, pos, f'Duplicate inline table key 
"{key_stem}"')
+            raise suffixed_err(src, pos, f"Duplicate inline table key 
{key_stem!r}")
         nest[key_stem] = value
         pos = skip_chars(src, pos, TOML_WS)
         c = src[pos : pos + 1]
@@ -473,7 +457,7 @@
 
 def parse_basic_str_escape(  # noqa: C901
     src: str, pos: Pos, *, multiline: bool = False
-) -> Tuple[Pos, str]:
+) -> tuple[Pos, str]:
     escape_id = src[pos : pos + 2]
     pos += 2
     if multiline and escape_id in {"\\ ", "\\\t", "\\\n"}:
@@ -498,15 +482,15 @@
         return pos, BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
     except KeyError:
         if len(escape_id) != 2:
-            raise suffixed_err(src, pos, "Unterminated string")
-        raise suffixed_err(src, pos, 'Unescaped "\\" in a string')
+            raise suffixed_err(src, pos, "Unterminated string") from None
+        raise suffixed_err(src, pos, 'Unescaped "\\" in a string') from None
 
 
-def parse_basic_str_escape_multiline(src: str, pos: Pos) -> Tuple[Pos, str]:
+def parse_basic_str_escape_multiline(src: str, pos: Pos) -> tuple[Pos, str]:
     return parse_basic_str_escape(src, pos, multiline=True)
 
 
-def parse_hex_char(src: str, pos: Pos, hex_len: int) -> Tuple[Pos, str]:
+def parse_hex_char(src: str, pos: Pos, hex_len: int) -> tuple[Pos, str]:
     hex_str = src[pos : pos + hex_len]
     if len(hex_str) != hex_len or not HEXDIGIT_CHARS.issuperset(hex_str):
         raise suffixed_err(src, pos, "Invalid hex value")
@@ -517,7 +501,7 @@
     return pos, chr(hex_int)
 
 
-def parse_literal_str(src: str, pos: Pos) -> Tuple[Pos, str]:
+def parse_literal_str(src: str, pos: Pos) -> tuple[Pos, str]:
     pos += 1  # Skip starting apostrophe
     start_pos = pos
     pos = skip_until(
@@ -526,7 +510,7 @@
     return pos + 1, src[start_pos:pos]  # Skip ending apostrophe
 
 
-def parse_multiline_str(src: str, pos: Pos, *, literal: bool) -> Tuple[Pos, 
str]:
+def parse_multiline_str(src: str, pos: Pos, *, literal: bool) -> tuple[Pos, 
str]:
     pos += 3
     if src.startswith("\n", pos):
         pos += 1
@@ -557,7 +541,7 @@
     return pos, result + (delim * 2)
 
 
-def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> Tuple[Pos, str]:
+def parse_basic_str(src: str, pos: Pos, *, multiline: bool) -> tuple[Pos, str]:
     if multiline:
         error_on = ILLEGAL_MULTILINE_BASIC_STR_CHARS
         parse_escapes = parse_basic_str_escape_multiline
@@ -570,7 +554,7 @@
         try:
             char = src[pos]
         except IndexError:
-            raise suffixed_err(src, pos, "Unterminated string")
+            raise suffixed_err(src, pos, "Unterminated string") from None
         if char == '"':
             if not multiline:
                 return pos + 1, result + src[start_pos:pos]
@@ -585,18 +569,20 @@
             start_pos = pos
             continue
         if char in error_on:
-            raise suffixed_err(src, pos, f'Illegal character "{char!r}"')
+            raise suffixed_err(src, pos, f"Illegal character {char!r}")
         pos += 1
 
 
 def parse_value(  # noqa: C901
     src: str, pos: Pos, parse_float: ParseFloat
-) -> Tuple[Pos, Any]:
+) -> tuple[Pos, Any]:
     try:
-        char: Optional[str] = src[pos]
+        char: str | None = src[pos]
     except IndexError:
         char = None
 
+    # IMPORTANT: order conditions based on speed of checking and likelihood
+
     # Basic strings
     if char == '"':
         if src.startswith('"""', pos):
@@ -617,13 +603,21 @@
         if src.startswith("false", pos):
             return pos + 5, False
 
+    # Arrays
+    if char == "[":
+        return parse_array(src, pos, parse_float)
+
+    # Inline tables
+    if char == "{":
+        return parse_inline_table(src, pos, parse_float)
+
     # Dates and times
     datetime_match = RE_DATETIME.match(src, pos)
     if datetime_match:
         try:
             datetime_obj = match_to_datetime(datetime_match)
-        except ValueError:
-            raise suffixed_err(src, pos, "Invalid date or datetime")
+        except ValueError as e:
+            raise suffixed_err(src, pos, "Invalid date or datetime") from e
         return datetime_match.end(), datetime_obj
     localtime_match = RE_LOCALTIME.match(src, pos)
     if localtime_match:
@@ -636,14 +630,6 @@
     if number_match:
         return number_match.end(), match_to_number(number_match, parse_float)
 
-    # Arrays
-    if char == "[":
-        return parse_array(src, pos, parse_float)
-
-    # Inline tables
-    if char == "{":
-        return parse_inline_table(src, pos, parse_float)
-
     # Special floats
     first_three = src[pos : pos + 3]
     if first_three in {"inf", "nan"}:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tomli/_re.py new/tomli-2.0.0/tomli/_re.py
--- old/tomli-1.2.1/tomli/_re.py        2021-08-05 22:07:21.000000000 +0200
+++ new/tomli-2.0.0/tomli/_re.py        2021-12-13 22:09:35.000000000 +0100
@@ -1,10 +1,11 @@
+from __future__ import annotations
+
 from datetime import date, datetime, time, timedelta, timezone, tzinfo
 from functools import lru_cache
 import re
-from typing import TYPE_CHECKING, Any, Optional, Union
+from typing import Any
 
-if TYPE_CHECKING:
-    from tomli._parser import ParseFloat
+from tomli._types import ParseFloat
 
 # E.g.
 # - 00:32:00.999999
@@ -35,16 +36,16 @@
     fr"""
 ([0-9]{{4}})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])  # date, e.g. 1988-10-27
 (?:
-    [T ]
+    [Tt ]
     {_TIME_RE_STR}
-    (?:(Z)|([+-])([01][0-9]|2[0-3]):([0-5][0-9]))?     # optional time offset
+    (?:([Zz])|([+-])([01][0-9]|2[0-3]):([0-5][0-9]))?  # optional time offset
 )?
 """,
     flags=re.VERBOSE,
 )
 
 
-def match_to_datetime(match: "re.Match") -> Union[datetime, date]:
+def match_to_datetime(match: re.Match) -> datetime | date:
     """Convert a `RE_DATETIME` match to `datetime.datetime` or `datetime.date`.
 
     Raises ValueError if the match does not correspond to a valid date
@@ -69,7 +70,7 @@
     hour, minute, sec = int(hour_str), int(minute_str), int(sec_str)
     micros = int(micros_str.ljust(6, "0")) if micros_str else 0
     if offset_sign_str:
-        tz: Optional[tzinfo] = cached_tz(
+        tz: tzinfo | None = cached_tz(
             offset_hour_str, offset_minute_str, offset_sign_str
         )
     elif zulu_time:
@@ -90,13 +91,13 @@
     )
 
 
-def match_to_localtime(match: "re.Match") -> time:
+def match_to_localtime(match: re.Match) -> time:
     hour_str, minute_str, sec_str, micros_str = match.groups()
     micros = int(micros_str.ljust(6, "0")) if micros_str else 0
     return time(int(hour_str), int(minute_str), int(sec_str), micros)
 
 
-def match_to_number(match: "re.Match", parse_float: "ParseFloat") -> Any:
+def match_to_number(match: re.Match, parse_float: ParseFloat) -> Any:
     if match.group("floatpart"):
         return parse_float(match.group())
     return int(match.group(), 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/tomli-1.2.1/tomli/_types.py 
new/tomli-2.0.0/tomli/_types.py
--- old/tomli-1.2.1/tomli/_types.py     1970-01-01 01:00:00.000000000 +0100
+++ new/tomli-2.0.0/tomli/_types.py     2021-12-13 22:09:35.000000000 +0100
@@ -0,0 +1,6 @@
+from typing import Any, Callable, Tuple
+
+# Type annotations
+ParseFloat = Callable[[str], Any]
+Key = Tuple[str, ...]
+Pos = int

Reply via email to