Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-flit-core for
openSUSE:Factory checked in at 2022-01-09 22:49:51
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-flit-core (Old)
and /work/SRC/openSUSE:Factory/.python-flit-core.new.1892 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-flit-core"
Sun Jan 9 22:49:51 2022 rev:8 rq:945129 version:3.6.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-flit-core/python-flit-core.changes
2021-10-25 15:17:33.165680110 +0200
+++
/work/SRC/openSUSE:Factory/.python-flit-core.new.1892/python-flit-core.changes
2022-01-09 22:49:55.635270832 +0100
@@ -1,0 +2,38 @@
+Sun Jan 9 14:53:21 UTC 2022 - Ben Greiner <[email protected]>
+
+- Back to bootstrap without pip
+
+-------------------------------------------------------------------
+Sun Jan 9 11:38:59 UTC 2022 - Ben Greiner <[email protected]>
+
+- Update to version 3.6
+ * flit_core now bundles the tomli TOML parser library (version
+ 1.2.3) to avoid a circular dependency between flit_core and
+ tomli (:ghpull:`492`). This means flit_core now has no
+ dependencies except Python itself, both at build time and at
+ runtime, simplifying :doc:`bootstrapping <bootstrap>`.
+- The above is not fully applicale to openSUSE, we debundle.
+- Release notes for Version 3.5.1
+ * Fix development installs with flit install --symlink and
+ --pth-file, which were broken in 3.5.0, especially for packages
+ using a src folder (:ghpull:`472`).
+- Release notes for Version 3.5
+ * You can now use Flit to distribute a module or package inside a
+ namespace package (as defined by PEP 420). To do this, specify
+ the import name of the concrete, inner module you are packaging
+ - e.g. name = "sphinxcontrib.foo" - either in the [project]
+ table, or under [tool.flit.module] if you want to use a
+ different name on PyPI (:ghpull:`468`).
+ * Flit no longer generates a setup.py file in sdists (.tar.gz
+ packages) by default (:ghpull:`462`). Modern packaging tools
+ don't need this. You can use the --setup-py flag to keep adding
+ it for now, but this will probably be removed at some point in
+ the future.
+ * Fixed how flit init handles authors' names with non-ASCII
+ characters (:ghpull:`460`).
+ * When flit init generates a LICENSE file, the new pyproject.toml
+ now references it (:ghpull:`467`).
+- Do not package tests
+- Make it work with old python-rpm-macros
+
+-------------------------------------------------------------------
Old:
----
flit_core-3.4.0.tar.gz
New:
----
build_dists.py
flit_core-3.6.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-flit-core.spec ++++++
--- /var/tmp/diff_new_pack.fErFr2/_old 2022-01-09 22:49:56.883271945 +0100
+++ /var/tmp/diff_new_pack.fErFr2/_new 2022-01-09 22:49:56.887271948 +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,17 +27,18 @@
%{?!python_module:%define python_module() python3-%{**}}
%define skip_python2 1
Name: python-flit-core%{psuffix}
-Version: 3.4.0
+Version: 3.6.0
Release: 0
Summary: Distribution-building parts of Flit
License: BSD-3-Clause
-URL: https://github.com/takluyver/flit
-Source:
https://files.pythonhosted.org/packages/source/f/flit-core/flit_core-%{version}.tar.gz
+URL: https://github.com/pypa/flit
+Source0:
https://files.pythonhosted.org/packages/source/f/flit-core/flit_core-%{version}.tar.gz
+Source1:
https://github.com/pypa/flit/raw/%{version}/flit_core/build_dists.py
BuildRequires: %{python_module base >= 3.6}
%if %{with test}
+BuildRequires: %{python_module flit-core = %{version}}
BuildRequires: %{python_module pytest}
BuildRequires: %{python_module testpath}
-BuildRequires: %{python_module tomli}
%endif
BuildRequires: fdupes
BuildRequires: python-rpm-macros
@@ -51,6 +52,7 @@
%prep
%setup -q -n flit_core-%{version}
+cp %{SOURCE1} .
%build
# https://flit.readthedocs.io/en/latest/bootstrap.html
@@ -63,13 +65,19 @@
unzip dist/flit_core-%{version}-py3-none-any.whl -d
%{buildroot}%{$python_sitelib}
rm -r %{buildroot}%{$python_sitelib}/flit_core/tests
}
-%python_compileall
+%{python_expand # debundle after the bootstrap. See vendor/README
+sed -i 's/from .vendor import tomli/import tomli/'
%{buildroot}%{$python_sitelib}/flit_core/config.py
+rm -r %{buildroot}%{$python_sitelib}/flit_core/vendor
+}
+%{?python_compileall}
%python_expand %fdupes %{buildroot}%{$python_sitelib}
%endif
%if %{with test}
%check
-%pytest
+# make sure we do not test the sources but the debundled package
+rm flit_core/*.py pyproject.toml
+%pytest -rfEs
%endif
%if !%{with test}
++++++ build_dists.py ++++++
"""Build flit_core to upload to PyPI.
Normally, this should only be used by me when making a release.
"""
import os
from flit_core import buildapi
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print("Building sdist")
sdist_fname = buildapi.build_sdist('dist/')
print(os.path.join('dist', sdist_fname))
print("\nBuilding wheel")
whl_fname = buildapi.build_wheel('dist/')
print(os.path.join('dist', whl_fname))
++++++ flit_core-3.4.0.tar.gz -> flit_core-3.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/PKG-INFO new/flit_core-3.6.0/PKG-INFO
--- old/flit_core-3.4.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,11 +1,9 @@
Metadata-Version: 2.1
Name: flit_core
-Version: 3.4.0
+Version: 3.6.0
Summary: Distribution-building parts of Flit. See flit package for more
information
-Home-page: https://github.com/takluyver/flit
-Author: Thomas Kluyver & contributors
-Author-email: [email protected]
+Author-email: Thomas Kluyver & contributors <[email protected]>
Requires-Python: >=3.6
Classifier: License :: OSI Approved :: BSD License
Classifier: Topic :: Software Development :: Libraries :: Python Modules
-Requires-Dist: tomli
+Project-URL: Source, https://github.com/pypa/flit
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/build_dists.py
new/flit_core-3.6.0/build_dists.py
--- old/flit_core-3.4.0/build_dists.py 2021-05-09 17:40:19.105348300 +0200
+++ new/flit_core-3.6.0/build_dists.py 1970-01-01 01:00:00.000000000 +0100
@@ -1,17 +0,0 @@
-"""Build flit_core to upload to PyPI.
-
-Normally, this should only be used by me when making a release.
-"""
-import os
-
-from flit_core import build_thyself
-
-os.chdir(os.path.dirname(os.path.abspath(__file__)))
-
-print("Building sdist")
-sdist_fname = build_thyself.build_sdist('dist/')
-print(os.path.join('dist', sdist_fname))
-
-print("\nBuilding wheel")
-whl_fname = build_thyself.build_wheel('dist/')
-print(os.path.join('dist', whl_fname))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/__init__.py
new/flit_core-3.6.0/flit_core/__init__.py
--- old/flit_core-3.4.0/flit_core/__init__.py 2021-10-10 11:29:14.143066200
+0200
+++ new/flit_core-3.6.0/flit_core/__init__.py 2021-12-27 14:38:33.710516700
+0100
@@ -4,4 +4,4 @@
All the convenient development features live in the main 'flit' package.
"""
-__version__ = '3.4.0'
+__version__ = '3.6.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/build_thyself.py
new/flit_core-3.6.0/flit_core/build_thyself.py
--- old/flit_core-3.4.0/flit_core/build_thyself.py 2021-10-10
11:14:23.714307800 +0200
+++ new/flit_core-3.6.0/flit_core/build_thyself.py 1970-01-01
01:00:00.000000000 +0100
@@ -1,95 +0,0 @@
-"""Bootstrapping backend
-
-This is *only* meant to build flit_core itself.
-Building any other packages occurs through flit_core.buildapi
-"""
-
-import io
-import os
-import os.path as osp
-from pathlib import Path
-import tempfile
-
-from .common import Metadata, Module, dist_info_name
-from .wheel import WheelBuilder, _write_wheel_file
-from .sdist import SdistBuilder
-
-from . import __version__
-
-metadata_dict = {
- 'name': 'flit_core',
- 'version': __version__,
- 'author': 'Thomas Kluyver & contributors',
- 'author_email': '[email protected]',
- 'home_page': 'https://github.com/takluyver/flit',
- 'summary': ('Distribution-building parts of Flit. '
- 'See flit package for more information'),
- 'requires_dist': [
- 'tomli',
- ],
- 'requires_python': '>=3.6',
- 'classifiers': [
- "License :: OSI Approved :: BSD License",
- "Topic :: Software Development :: Libraries :: Python Modules",
- ]
-}
-metadata = Metadata(metadata_dict)
-
-def get_requires_for_build_wheel(config_settings=None):
- """Returns a list of requirements for building, as strings"""
- return []
-
-def get_requires_for_build_sdist(config_settings=None):
- """Returns a list of requirements for building, as strings"""
- return []
-
-def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
- """Creates {metadata_directory}/foo-1.2.dist-info"""
- dist_info = osp.join(metadata_directory,
- dist_info_name(metadata.name, metadata.version))
- os.mkdir(dist_info)
-
- with open(osp.join(dist_info, 'WHEEL'), 'w') as f:
- _write_wheel_file(f, supports_py2=metadata.supports_py2)
-
- with open(osp.join(dist_info, 'METADATA'), 'w') as f:
- metadata.write_metadata_file(f)
-
- return osp.basename(dist_info)
-
-def build_wheel(wheel_directory, config_settings=None,
metadata_directory=None):
- """Builds a wheel, places it in wheel_directory"""
- cwd = Path.cwd()
- module = Module('flit_core', cwd)
-
- # We don't know the final filename until metadata is loaded, so write to
- # a temporary_file, and rename it afterwards.
- (fd, temp_path) = tempfile.mkstemp(suffix='.whl', dir=str(wheel_directory))
- try:
- with io.open(fd, 'w+b') as fp:
- wb = WheelBuilder(
- cwd, module, metadata, entrypoints={}, target_fp=fp
- )
- wb.build()
-
- wheel_path = osp.join(wheel_directory, wb.wheel_filename)
- os.replace(temp_path, wheel_path)
- except:
- os.unlink(temp_path)
- raise
-
- return wb.wheel_filename
-
-def build_sdist(sdist_directory, config_settings=None):
- """Builds an sdist, places it in sdist_directory"""
- cwd = Path.cwd()
- module = Module('flit_core', cwd)
- reqs_by_extra = {'.none': metadata.requires}
-
- sb = SdistBuilder(
- module, metadata, cwd, reqs_by_extra, entrypoints={},
- extra_files=['pyproject.toml', 'build_dists.py']
- )
- path = sb.build(Path(sdist_directory))
- return path.name
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/common.py
new/flit_core-3.6.0/flit_core/common.py
--- old/flit_core-3.4.0/flit_core/common.py 2021-05-09 17:40:19.105348300
+0200
+++ new/flit_core-3.6.0/flit_core/common.py 2021-11-23 12:08:18.530732200
+0100
@@ -3,7 +3,7 @@
import hashlib
import logging
import os
-import os.path as osp
+
from pathlib import Path
import re
@@ -14,15 +14,18 @@
class Module(object):
"""This represents the module/package that we are going to distribute
"""
+ in_namespace_package = False
+ namespace_package_name = None
+
def __init__(self, name, directory=Path()):
self.name = name
- self.directory = directory
# It must exist either as a .py file or a directory, but not both
- pkg_dir = directory / name
- py_file = directory / (name+'.py')
- src_pkg_dir = directory / 'src' / name
- src_py_file = directory / 'src' / (name+'.py')
+ name_as_path = name.replace('.', os.sep)
+ pkg_dir = directory / name_as_path
+ py_file = directory / (name_as_path+'.py')
+ src_pkg_dir = directory / 'src' / name_as_path
+ src_py_file = directory / 'src' / (name_as_path+'.py')
existing = set()
if pkg_dir.is_dir():
@@ -54,10 +57,11 @@
elif not existing:
raise ValueError("No file/folder found for module {}".format(name))
- @property
- def source_dir(self):
- """Path of folder containing the module (src/ or project root)"""
- return self.path.parent
+ self.source_dir = directory / self.prefix
+
+ if '.' in name:
+ self.namespace_package_name = name.rpartition('.')[0]
+ self.in_namespace_package = True
@property
def file(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/config.py
new/flit_core-3.6.0/flit_core/config.py
--- old/flit_core-3.4.0/flit_core/config.py 2021-10-01 10:16:06.493757700
+0200
+++ new/flit_core-3.6.0/flit_core/config.py 2021-12-27 14:04:58.924610600
+0100
@@ -5,9 +5,9 @@
import os
import os.path as osp
from pathlib import Path
-import tomli
import re
+from .vendor import tomli
from .versionno import normalise_version
log = logging.getLogger(__name__)
@@ -287,7 +287,7 @@
res = LoadedConfig()
res.module = md_sect.get('module')
- if not str.isidentifier(res.module):
+ if not all([m.isidentifier() for m in res.module.split(".")]):
raise ConfigError("Module name %r is not a valid identifier" %
res.module)
md_dict = res.metadata
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/tests/samples/module2.py
new/flit_core-3.6.0/flit_core/tests/samples/module2.py
--- old/flit_core-3.4.0/flit_core/tests/samples/module2.py 2021-05-09
17:40:19.106348500 +0200
+++ new/flit_core-3.6.0/flit_core/tests/samples/module2.py 2021-12-06
15:34:44.137786100 +0100
@@ -4,7 +4,7 @@
a = {}
# An assignment to a subscript (a['test']) broke introspection
-# https://github.com/takluyver/flit/issues/343
+# https://github.com/pypa/flit/issues/343
a['test'] = 6
__version__ = '7.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/flit_core-3.4.0/flit_core/tests/samples/ns1-pkg/EG_README.rst
new/flit_core-3.6.0/flit_core/tests/samples/ns1-pkg/EG_README.rst
--- old/flit_core-3.4.0/flit_core/tests/samples/ns1-pkg/EG_README.rst
1970-01-01 01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/tests/samples/ns1-pkg/EG_README.rst
2021-11-18 23:10:43.577393000 +0100
@@ -0,0 +1,4 @@
+This is an example long description for tests to load.
+
+This file is `valid reStructuredText
+<http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html>`_.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/flit_core-3.4.0/flit_core/tests/samples/ns1-pkg/ns1/pkg/__init__.py
new/flit_core-3.6.0/flit_core/tests/samples/ns1-pkg/ns1/pkg/__init__.py
--- old/flit_core-3.4.0/flit_core/tests/samples/ns1-pkg/ns1/pkg/__init__.py
1970-01-01 01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/tests/samples/ns1-pkg/ns1/pkg/__init__.py
2021-11-18 23:10:43.577393000 +0100
@@ -0,0 +1,8 @@
+"""
+==================
+ns1.pkg
+==================
+"""
+
+__version__ = '0.1'
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/flit_core-3.4.0/flit_core/tests/samples/ns1-pkg/pyproject.toml
new/flit_core-3.6.0/flit_core/tests/samples/ns1-pkg/pyproject.toml
--- old/flit_core-3.4.0/flit_core/tests/samples/ns1-pkg/pyproject.toml
1970-01-01 01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/tests/samples/ns1-pkg/pyproject.toml
2021-11-18 23:10:43.577393000 +0100
@@ -0,0 +1,10 @@
+[build-system]
+requires = ["flit_core >=3.5,<4"]
+build-backend = "flit_core.buildapi"
+
+[tool.flit.metadata]
+module = "ns1.pkg"
+author = "Sir Robin"
+author-email = "[email protected]"
+home-page = "http://github.com/sirrobin/module1"
+description-file = "EG_README.rst"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/flit_core-3.4.0/flit_core/tests/test_build_thyself.py
new/flit_core-3.6.0/flit_core/tests/test_build_thyself.py
--- old/flit_core-3.4.0/flit_core/tests/test_build_thyself.py 2021-05-09
17:40:19.108348400 +0200
+++ new/flit_core-3.6.0/flit_core/tests/test_build_thyself.py 2021-12-27
14:04:58.924610600 +0100
@@ -1,3 +1,4 @@
+"""Tests of flit_core building itself"""
import os
import os.path as osp
import pytest
@@ -5,11 +6,11 @@
from testpath import assert_isdir, assert_isfile
import zipfile
-from flit_core import build_thyself
+from flit_core import buildapi
@pytest.fixture()
def cwd_project():
- proj_dir = osp.dirname(osp.dirname(osp.abspath(build_thyself.__file__)))
+ proj_dir = osp.dirname(osp.dirname(osp.abspath(buildapi.__file__)))
if not osp.isfile(osp.join(proj_dir, 'pyproject.toml')):
pytest.skip("need flit_core source directory")
@@ -21,9 +22,9 @@
os.chdir(old_cwd)
-def test_prepare_metadata(tmp_path):
+def test_prepare_metadata(tmp_path, cwd_project):
tmp_path = str(tmp_path)
- dist_info = build_thyself.prepare_metadata_for_build_wheel(tmp_path)
+ dist_info = buildapi.prepare_metadata_for_build_wheel(tmp_path)
assert dist_info.endswith('.dist-info')
assert dist_info.startswith('flit_core')
@@ -36,7 +37,7 @@
def test_wheel(tmp_path, cwd_project):
tmp_path = str(tmp_path)
- filename = build_thyself.build_wheel(tmp_path)
+ filename = buildapi.build_wheel(tmp_path)
assert filename.endswith('.whl')
assert filename.startswith('flit_core')
@@ -47,7 +48,7 @@
def test_sdist(tmp_path, cwd_project):
tmp_path = str(tmp_path)
- filename = build_thyself.build_sdist(tmp_path)
+ filename = buildapi.build_sdist(tmp_path)
assert filename.endswith('.tar.gz')
assert filename.startswith('flit_core')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/tests/test_common.py
new/flit_core-3.6.0/flit_core/tests/test_common.py
--- old/flit_core-3.4.0/flit_core/tests/test_common.py 2021-05-09
17:40:19.108348400 +0200
+++ new/flit_core-3.6.0/flit_core/tests/test_common.py 2021-11-18
23:10:43.577393000 +0100
@@ -14,6 +14,15 @@
samples_dir = Path(__file__).parent / 'samples'
class ModuleTests(TestCase):
+ def test_ns_package_importable(self):
+ i = Module('ns1.pkg', samples_dir / 'ns1-pkg')
+ assert i.path == Path(samples_dir, 'ns1-pkg', 'ns1', 'pkg')
+ assert i.file == Path(samples_dir, 'ns1-pkg', 'ns1', 'pkg',
'__init__.py')
+ assert i.is_package
+
+ assert i.in_namespace_package
+ assert i.namespace_package_name == 'ns1'
+
def test_package_importable(self):
i = Module('package1', samples_dir)
assert i.path == samples_dir / 'package1'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/tests/test_config.py
new/flit_core-3.6.0/flit_core/tests/test_config.py
--- old/flit_core-3.4.0/flit_core/tests/test_config.py 2021-08-19
19:07:06.144217700 +0200
+++ new/flit_core-3.6.0/flit_core/tests/test_config.py 2021-11-18
23:10:43.578393000 +0100
@@ -15,6 +15,11 @@
assert inf.module == 'module1'
assert inf.metadata['home_page'] == 'http://github.com/sirrobin/module1'
+def test_load_toml_ns():
+ inf = config.read_flit_config(samples_dir / 'ns1-pkg' / 'pyproject.toml')
+ assert inf.module == 'ns1.pkg'
+ assert inf.metadata['home_page'] == 'http://github.com/sirrobin/module1'
+
def test_load_pep621():
inf = config.read_flit_config(samples_dir / 'pep621' / 'pyproject.toml')
assert inf.module == 'module1a'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/tests/test_wheel.py
new/flit_core-3.6.0/flit_core/tests/test_wheel.py
--- old/flit_core-3.4.0/flit_core/tests/test_wheel.py 2021-10-06
21:26:07.727812800 +0200
+++ new/flit_core-3.6.0/flit_core/tests/test_wheel.py 2021-12-06
15:34:44.137786100 +0100
@@ -8,7 +8,7 @@
samples_dir = Path(__file__).parent / 'samples'
def test_licenses_dir(tmp_path):
- # Smoketest for https://github.com/takluyver/flit/issues/399
+ # Smoketest for https://github.com/pypa/flit/issues/399
info = make_wheel_in(samples_dir / 'inclusion' / 'pyproject.toml',
tmp_path)
assert_isfile(info.file)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/vendor/README
new/flit_core-3.6.0/flit_core/vendor/README
--- old/flit_core-3.4.0/flit_core/vendor/README 1970-01-01 01:00:00.000000000
+0100
+++ new/flit_core-3.6.0/flit_core/vendor/README 2021-12-27 14:04:58.925610500
+0100
@@ -0,0 +1,13 @@
+flit_core bundles the 'tomli' TOML parser, to avoid a bootstrapping problem.
+tomli is packaged using Flit, so there would be a dependency cycle when
building
+from source. Vendoring a copy of tomli avoids this. The code in tomli is under
+the MIT license, and the LICENSE file is in the .dist-info folder.
+
+If you want to unbundle tomli and rely on it as a separate package, you can
+replace the package with Python code doing 'from tomli import *'. You will
+probably need to work around the dependency cycle between flit_core and tomli.
+
+Bundling a TOML parser should be a special case - I don't plan on bundling
+anything else in flit_core (or depending on any other packages).
+I hope that a TOML parser will be added to the Python standard library, and
then
+this bundled parser will go away.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/vendor/tomli/__init__.py
new/flit_core-3.6.0/flit_core/vendor/tomli/__init__.py
--- old/flit_core-3.4.0/flit_core/vendor/tomli/__init__.py 1970-01-01
01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli/__init__.py 2021-12-27
14:04:58.927610600 +0100
@@ -0,0 +1,9 @@
+"""A lil' TOML parser."""
+
+__all__ = ("loads", "load", "TOMLDecodeError")
+__version__ = "1.2.3" # DO NOT EDIT THIS LINE MANUALLY. LET bump2version
UTILITY DO IT
+
+from ._parser import TOMLDecodeError, load, loads
+
+# Pretend this exception was created here.
+TOMLDecodeError.__module__ = "tomli"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/vendor/tomli/_parser.py
new/flit_core-3.6.0/flit_core/vendor/tomli/_parser.py
--- old/flit_core-3.4.0/flit_core/vendor/tomli/_parser.py 1970-01-01
01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli/_parser.py 2021-12-27
14:04:58.927610600 +0100
@@ -0,0 +1,663 @@
+import string
+from types import MappingProxyType
+from typing import Any, BinaryIO, Dict, FrozenSet, Iterable, NamedTuple,
Optional, Tuple
+import warnings
+
+from ._re import (
+ RE_DATETIME,
+ RE_LOCALTIME,
+ RE_NUMBER,
+ match_to_datetime,
+ match_to_localtime,
+ match_to_number,
+)
+from ._types import Key, ParseFloat, Pos
+
+ASCII_CTRL = frozenset(chr(i) for i in range(32)) | frozenset(chr(127))
+
+# Neither of these sets include quotation mark or backslash. They are
+# currently handled as separate cases in the parser functions.
+ILLEGAL_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t")
+ILLEGAL_MULTILINE_BASIC_STR_CHARS = ASCII_CTRL - frozenset("\t\n")
+
+ILLEGAL_LITERAL_STR_CHARS = ILLEGAL_BASIC_STR_CHARS
+ILLEGAL_MULTILINE_LITERAL_STR_CHARS = ILLEGAL_MULTILINE_BASIC_STR_CHARS
+
+ILLEGAL_COMMENT_CHARS = ILLEGAL_BASIC_STR_CHARS
+
+TOML_WS = frozenset(" \t")
+TOML_WS_AND_NEWLINE = TOML_WS | frozenset("\n")
+BARE_KEY_CHARS = frozenset(string.ascii_letters + string.digits + "-_")
+KEY_INITIAL_CHARS = BARE_KEY_CHARS | frozenset("\"'")
+HEXDIGIT_CHARS = frozenset(string.hexdigits)
+
+BASIC_STR_ESCAPE_REPLACEMENTS = MappingProxyType(
+ {
+ "\\b": "\u0008", # backspace
+ "\\t": "\u0009", # tab
+ "\\n": "\u000A", # linefeed
+ "\\f": "\u000C", # form feed
+ "\\r": "\u000D", # carriage return
+ '\\"': "\u0022", # quote
+ "\\\\": "\u005C", # backslash
+ }
+)
+
+
+class TOMLDecodeError(ValueError):
+ """An error raised if a document is not valid TOML."""
+
+
+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,
+ stacklevel=2,
+ )
+ s = s_bytes # type: ignore[assignment]
+ return loads(s, parse_float=parse_float)
+
+
+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")
+ pos = 0
+ out = Output(NestedDict(), Flags())
+ header: Key = ()
+
+ # Parse one statement at a time
+ # (typically means one line in TOML source)
+ while True:
+ # 1. Skip line leading whitespace
+ pos = skip_chars(src, pos, TOML_WS)
+
+ # 2. Parse rules. Expect one of the following:
+ # - end of file
+ # - end of line
+ # - comment
+ # - key/value pair
+ # - append dict to list (and move to its namespace)
+ # - create dict (and move to its namespace)
+ # Skip trailing whitespace when applicable.
+ try:
+ char = src[pos]
+ except IndexError:
+ break
+ if char == "\n":
+ pos += 1
+ continue
+ if char in KEY_INITIAL_CHARS:
+ pos = key_value_rule(src, pos, out, header, parse_float)
+ pos = skip_chars(src, pos, TOML_WS)
+ elif char == "[":
+ try:
+ second_char: Optional[str] = src[pos + 1]
+ except IndexError:
+ second_char = None
+ if second_char == "[":
+ pos, header = create_list_rule(src, pos, out)
+ else:
+ pos, header = create_dict_rule(src, pos, out)
+ pos = skip_chars(src, pos, TOML_WS)
+ elif char != "#":
+ raise suffixed_err(src, pos, "Invalid statement")
+
+ # 3. Skip comment
+ pos = skip_comment(src, pos)
+
+ # 4. Expect end of line or end of file
+ try:
+ char = src[pos]
+ except IndexError:
+ break
+ if char != "\n":
+ raise suffixed_err(
+ src, pos, "Expected newline or end of document after a
statement"
+ )
+ pos += 1
+
+ return out.data.dict
+
+
+class Flags:
+ """Flags that map to parsed keys/namespaces."""
+
+ # Marks an immutable namespace (inline array or inline table).
+ FROZEN = 0
+ # Marks a nest that has been explicitly created and can no longer
+ # be opened using the "[table]" syntax.
+ EXPLICIT_NEST = 1
+
+ def __init__(self) -> None:
+ self._flags: Dict[str, dict] = {}
+
+ def unset_all(self, key: Key) -> None:
+ cont = self._flags
+ for k in key[:-1]:
+ if k not in cont:
+ return
+ 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]
+ for k in key_parent:
+ if k not in cont:
+ cont[k] = {"flags": set(), "recursive_flags": set(), "nested":
{}}
+ cont = cont[k]["nested"]
+ if key_stem not in cont:
+ cont[key_stem] = {"flags": set(), "recursive_flags": set(),
"nested": {}}
+ cont[key_stem]["recursive_flags" if recursive else "flags"].add(flag)
+
+ def is_(self, key: Key, flag: int) -> bool:
+ if not key:
+ return False # document root has no flags
+ cont = self._flags
+ for k in key[:-1]:
+ if k not in cont:
+ return False
+ inner_cont = cont[k]
+ if flag in inner_cont["recursive_flags"]:
+ return True
+ cont = inner_cont["nested"]
+ key_stem = key[-1]
+ if key_stem in cont:
+ cont = cont[key_stem]
+ return flag in cont["flags"] or flag in cont["recursive_flags"]
+ return False
+
+
+class NestedDict:
+ def __init__(self) -> None:
+ # The parsed content of the TOML document
+ self.dict: Dict[str, Any] = {}
+
+ def get_or_create_nest(
+ self,
+ key: Key,
+ *,
+ access_lists: bool = True,
+ ) -> dict:
+ cont: Any = self.dict
+ for k in key:
+ if k not in cont:
+ cont[k] = {}
+ cont = cont[k]
+ if access_lists and isinstance(cont, list):
+ cont = cont[-1]
+ if not isinstance(cont, dict):
+ raise KeyError("There is no nest behind this key")
+ return cont
+
+ def append_nest_to_list(self, key: Key) -> None:
+ cont = self.get_or_create_nest(key[:-1])
+ last_key = key[-1]
+ if last_key in cont:
+ list_ = cont[last_key]
+ try:
+ list_.append({})
+ except AttributeError:
+ raise KeyError("An object other than list found behind this
key")
+ else:
+ cont[last_key] = [{}]
+
+
+class Output(NamedTuple):
+ data: NestedDict
+ flags: Flags
+
+
+def skip_chars(src: str, pos: Pos, chars: Iterable[str]) -> Pos:
+ try:
+ while src[pos] in chars:
+ pos += 1
+ except IndexError:
+ pass
+ return pos
+
+
+def skip_until(
+ src: str,
+ pos: Pos,
+ expect: str,
+ *,
+ error_on: FrozenSet[str],
+ error_on_eof: bool,
+) -> Pos:
+ try:
+ new_pos = src.index(expect, pos)
+ except ValueError:
+ new_pos = len(src)
+ if error_on_eof:
+ 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}")
+ return new_pos
+
+
+def skip_comment(src: str, pos: Pos) -> Pos:
+ try:
+ char: Optional[str] = src[pos]
+ except IndexError:
+ char = None
+ if char == "#":
+ return skip_until(
+ src, pos + 1, "\n", error_on=ILLEGAL_COMMENT_CHARS,
error_on_eof=False
+ )
+ return pos
+
+
+def skip_comments_and_array_ws(src: str, pos: Pos) -> Pos:
+ while True:
+ pos_before_skip = pos
+ pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE)
+ pos = skip_comment(src, pos)
+ if pos == pos_before_skip:
+ return pos
+
+
+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)
+
+ if out.flags.is_(key, Flags.EXPLICIT_NEST) or out.flags.is_(key,
Flags.FROZEN):
+ raise suffixed_err(src, pos, f"Can not declare {key} twice")
+ out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False)
+ try:
+ out.data.get_or_create_nest(key)
+ except KeyError:
+ 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]:
+ pos += 2 # Skip "[["
+ pos = skip_chars(src, pos, TOML_WS)
+ pos, key = parse_key(src, pos)
+
+ if out.flags.is_(key, Flags.FROZEN):
+ raise suffixed_err(src, pos, f"Can not mutate immutable namespace
{key}")
+ # Free the namespace now that it points to another empty list item...
+ out.flags.unset_all(key)
+ # ...but this key precisely is still prohibited from table declaration
+ out.flags.set(key, Flags.EXPLICIT_NEST, recursive=False)
+ try:
+ out.data.append_nest_to_list(key)
+ except KeyError:
+ 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')
+ return pos + 2, key
+
+
+def key_value_rule(
+ src: str, pos: Pos, out: Output, header: Key, parse_float: ParseFloat
+) -> Pos:
+ pos, key, value = parse_key_value_pair(src, pos, parse_float)
+ key_parent, key_stem = key[:-1], key[-1]
+ abs_key_parent = header + key_parent
+
+ if out.flags.is_(abs_key_parent, Flags.FROZEN):
+ raise suffixed_err(
+ src, pos, f"Can not 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") 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
+ if isinstance(value, (dict, list)):
+ out.flags.set(header + key, Flags.FROZEN, recursive=True)
+ nest[key_stem] = value
+ return pos
+
+
+def parse_key_value_pair(
+ src: str, pos: Pos, parse_float: ParseFloat
+) -> Tuple[Pos, Key, Any]:
+ pos, key = parse_key(src, pos)
+ try:
+ char: Optional[str] = src[pos]
+ except IndexError:
+ char = None
+ if char != "=":
+ raise suffixed_err(src, pos, 'Expected "=" after a key in a key/value
pair')
+ pos += 1
+ pos = skip_chars(src, pos, TOML_WS)
+ pos, value = parse_value(src, pos, parse_float)
+ return pos, key, value
+
+
+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]
+ except IndexError:
+ char = None
+ if char != ".":
+ return pos, key
+ pos += 1
+ pos = skip_chars(src, pos, TOML_WS)
+ pos, key_part = parse_key_part(src, pos)
+ key += (key_part,)
+ pos = skip_chars(src, pos, TOML_WS)
+
+
+def parse_key_part(src: str, pos: Pos) -> Tuple[Pos, str]:
+ try:
+ char: Optional[str] = src[pos]
+ except IndexError:
+ char = None
+ if char in BARE_KEY_CHARS:
+ start_pos = pos
+ pos = skip_chars(src, pos, BARE_KEY_CHARS)
+ return pos, src[start_pos:pos]
+ if char == "'":
+ return parse_literal_str(src, pos)
+ if char == '"':
+ return parse_one_line_basic_str(src, pos)
+ 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]:
+ pos += 1
+ return parse_basic_str(src, pos, multiline=False)
+
+
+def parse_array(src: str, pos: Pos, parse_float: ParseFloat) -> Tuple[Pos,
list]:
+ pos += 1
+ array: list = []
+
+ pos = skip_comments_and_array_ws(src, pos)
+ if src.startswith("]", pos):
+ return pos + 1, array
+ while True:
+ pos, val = parse_value(src, pos, parse_float)
+ array.append(val)
+ pos = skip_comments_and_array_ws(src, pos)
+
+ c = src[pos : pos + 1]
+ if c == "]":
+ return pos + 1, array
+ if c != ",":
+ raise suffixed_err(src, pos, "Unclosed array")
+ pos += 1
+
+ pos = skip_comments_and_array_ws(src, pos)
+ if src.startswith("]", pos):
+ return pos + 1, array
+
+
+def parse_inline_table(src: str, pos: Pos, parse_float: ParseFloat) ->
Tuple[Pos, dict]:
+ pos += 1
+ nested_dict = NestedDict()
+ flags = Flags()
+
+ pos = skip_chars(src, pos, TOML_WS)
+ if src.startswith("}", pos):
+ return pos + 1, nested_dict.dict
+ while True:
+ pos, key, value = parse_key_value_pair(src, pos, parse_float)
+ key_parent, key_stem = key[:-1], key[-1]
+ if flags.is_(key, Flags.FROZEN):
+ raise suffixed_err(src, pos, f"Can not mutate immutable namespace
{key}")
+ 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") from None
+ if key_stem in nest:
+ 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]
+ if c == "}":
+ return pos + 1, nested_dict.dict
+ if c != ",":
+ raise suffixed_err(src, pos, "Unclosed inline table")
+ if isinstance(value, (dict, list)):
+ flags.set(key, Flags.FROZEN, recursive=True)
+ pos += 1
+ pos = skip_chars(src, pos, TOML_WS)
+
+
+def parse_basic_str_escape( # noqa: C901
+ src: str, pos: Pos, *, multiline: bool = False
+) -> Tuple[Pos, str]:
+ escape_id = src[pos : pos + 2]
+ pos += 2
+ if multiline and escape_id in {"\\ ", "\\\t", "\\\n"}:
+ # Skip whitespace until next non-whitespace character or end of
+ # the doc. Error if non-whitespace is found before newline.
+ if escape_id != "\\\n":
+ pos = skip_chars(src, pos, TOML_WS)
+ try:
+ char = src[pos]
+ except IndexError:
+ return pos, ""
+ if char != "\n":
+ raise suffixed_err(src, pos, 'Unescaped "\\" in a string')
+ pos += 1
+ pos = skip_chars(src, pos, TOML_WS_AND_NEWLINE)
+ return pos, ""
+ if escape_id == "\\u":
+ return parse_hex_char(src, pos, 4)
+ if escape_id == "\\U":
+ return parse_hex_char(src, pos, 8)
+ try:
+ return pos, BASIC_STR_ESCAPE_REPLACEMENTS[escape_id]
+ except KeyError:
+ if len(escape_id) != 2:
+ 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]:
+ return parse_basic_str_escape(src, pos, multiline=True)
+
+
+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")
+ pos += hex_len
+ hex_int = int(hex_str, 16)
+ if not is_unicode_scalar_value(hex_int):
+ raise suffixed_err(src, pos, "Escaped character is not a Unicode
scalar value")
+ return pos, chr(hex_int)
+
+
+def parse_literal_str(src: str, pos: Pos) -> Tuple[Pos, str]:
+ pos += 1 # Skip starting apostrophe
+ start_pos = pos
+ pos = skip_until(
+ src, pos, "'", error_on=ILLEGAL_LITERAL_STR_CHARS, error_on_eof=True
+ )
+ return pos + 1, src[start_pos:pos] # Skip ending apostrophe
+
+
+def parse_multiline_str(src: str, pos: Pos, *, literal: bool) -> Tuple[Pos,
str]:
+ pos += 3
+ if src.startswith("\n", pos):
+ pos += 1
+
+ if literal:
+ delim = "'"
+ end_pos = skip_until(
+ src,
+ pos,
+ "'''",
+ error_on=ILLEGAL_MULTILINE_LITERAL_STR_CHARS,
+ error_on_eof=True,
+ )
+ result = src[pos:end_pos]
+ pos = end_pos + 3
+ else:
+ delim = '"'
+ pos, result = parse_basic_str(src, pos, multiline=True)
+
+ # Add at maximum two extra apostrophes/quotes if the end sequence
+ # is 4 or 5 chars long instead of just 3.
+ if not src.startswith(delim, pos):
+ return pos, result
+ pos += 1
+ if not src.startswith(delim, pos):
+ return pos, result + delim
+ pos += 1
+ return pos, result + (delim * 2)
+
+
+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
+ else:
+ error_on = ILLEGAL_BASIC_STR_CHARS
+ parse_escapes = parse_basic_str_escape
+ result = ""
+ start_pos = pos
+ while True:
+ try:
+ char = src[pos]
+ except IndexError:
+ raise suffixed_err(src, pos, "Unterminated string") from None
+ if char == '"':
+ if not multiline:
+ return pos + 1, result + src[start_pos:pos]
+ if src.startswith('"""', pos):
+ return pos + 3, result + src[start_pos:pos]
+ pos += 1
+ continue
+ if char == "\\":
+ result += src[start_pos:pos]
+ pos, parsed_escape = parse_escapes(src, pos)
+ result += parsed_escape
+ start_pos = pos
+ continue
+ if char in error_on:
+ 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]:
+ try:
+ char: Optional[str] = src[pos]
+ except IndexError:
+ char = None
+
+ # Basic strings
+ if char == '"':
+ if src.startswith('"""', pos):
+ return parse_multiline_str(src, pos, literal=False)
+ return parse_one_line_basic_str(src, pos)
+
+ # Literal strings
+ if char == "'":
+ if src.startswith("'''", pos):
+ return parse_multiline_str(src, pos, literal=True)
+ return parse_literal_str(src, pos)
+
+ # Booleans
+ if char == "t":
+ if src.startswith("true", pos):
+ return pos + 4, True
+ if char == "f":
+ if src.startswith("false", pos):
+ return pos + 5, False
+
+ # Dates and times
+ datetime_match = RE_DATETIME.match(src, pos)
+ if datetime_match:
+ try:
+ datetime_obj = match_to_datetime(datetime_match)
+ 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:
+ return localtime_match.end(), match_to_localtime(localtime_match)
+
+ # Integers and "normal" floats.
+ # The regex will greedily match any type starting with a decimal
+ # char, so needs to be located after handling of dates and times.
+ number_match = RE_NUMBER.match(src, pos)
+ 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"}:
+ return pos + 3, parse_float(first_three)
+ first_four = src[pos : pos + 4]
+ if first_four in {"-inf", "+inf", "-nan", "+nan"}:
+ return pos + 4, parse_float(first_four)
+
+ raise suffixed_err(src, pos, "Invalid value")
+
+
+def suffixed_err(src: str, pos: Pos, msg: str) -> TOMLDecodeError:
+ """Return a `TOMLDecodeError` where error message is suffixed with
+ coordinates in source."""
+
+ def coord_repr(src: str, pos: Pos) -> str:
+ if pos >= len(src):
+ return "end of document"
+ line = src.count("\n", 0, pos) + 1
+ if line == 1:
+ column = pos + 1
+ else:
+ column = pos - src.rindex("\n", 0, pos)
+ return f"line {line}, column {column}"
+
+ return TOMLDecodeError(f"{msg} (at {coord_repr(src, pos)})")
+
+
+def is_unicode_scalar_value(codepoint: int) -> bool:
+ return (0 <= codepoint <= 55295) or (57344 <= codepoint <= 1114111)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/vendor/tomli/_re.py
new/flit_core-3.6.0/flit_core/vendor/tomli/_re.py
--- old/flit_core-3.4.0/flit_core/vendor/tomli/_re.py 1970-01-01
01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli/_re.py 2021-12-27
14:04:58.927610600 +0100
@@ -0,0 +1,101 @@
+from datetime import date, datetime, time, timedelta, timezone, tzinfo
+from functools import lru_cache
+import re
+from typing import Any, Optional, Union
+
+from ._types import ParseFloat
+
+# E.g.
+# - 00:32:00.999999
+# - 00:32:00
+_TIME_RE_STR =
r"([01][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])(?:\.([0-9]{1,6})[0-9]*)?"
+
+RE_NUMBER = re.compile(
+ r"""
+0
+(?:
+ x[0-9A-Fa-f](?:_?[0-9A-Fa-f])* # hex
+ |
+ b[01](?:_?[01])* # bin
+ |
+ o[0-7](?:_?[0-7])* # oct
+)
+|
+[+-]?(?:0|[1-9](?:_?[0-9])*) # dec, integer part
+(?P<floatpart>
+ (?:\.[0-9](?:_?[0-9])*)? # optional fractional part
+ (?:[eE][+-]?[0-9](?:_?[0-9])*)? # optional exponent part
+)
+""",
+ flags=re.VERBOSE,
+)
+RE_LOCALTIME = re.compile(_TIME_RE_STR)
+RE_DATETIME = re.compile(
+ fr"""
+([0-9]{{4}})-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01]) # date, e.g. 1988-10-27
+(?:
+ [Tt ]
+ {_TIME_RE_STR}
+ (?:([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]:
+ """Convert a `RE_DATETIME` match to `datetime.datetime` or `datetime.date`.
+
+ Raises ValueError if the match does not correspond to a valid date
+ or datetime.
+ """
+ (
+ year_str,
+ month_str,
+ day_str,
+ hour_str,
+ minute_str,
+ sec_str,
+ micros_str,
+ zulu_time,
+ offset_sign_str,
+ offset_hour_str,
+ offset_minute_str,
+ ) = match.groups()
+ year, month, day = int(year_str), int(month_str), int(day_str)
+ if hour_str is None:
+ return date(year, month, day)
+ 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(
+ offset_hour_str, offset_minute_str, offset_sign_str
+ )
+ elif zulu_time:
+ tz = timezone.utc
+ else: # local date-time
+ tz = None
+ return datetime(year, month, day, hour, minute, sec, micros, tzinfo=tz)
+
+
+@lru_cache(maxsize=None)
+def cached_tz(hour_str: str, minute_str: str, sign_str: str) -> timezone:
+ sign = 1 if sign_str == "+" else -1
+ return timezone(
+ timedelta(
+ hours=sign * int(hour_str),
+ minutes=sign * int(minute_str),
+ )
+ )
+
+
+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:
+ 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/flit_core-3.4.0/flit_core/vendor/tomli/_types.py
new/flit_core-3.6.0/flit_core/vendor/tomli/_types.py
--- old/flit_core-3.4.0/flit_core/vendor/tomli/_types.py 1970-01-01
01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli/_types.py 2021-12-27
14:04:58.927610600 +0100
@@ -0,0 +1,6 @@
+from typing import Any, Callable, Tuple
+
+# Type annotations
+ParseFloat = Callable[[str], Any]
+Key = Tuple[str, ...]
+Pos = int
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/flit_core/vendor/tomli/py.typed
new/flit_core-3.6.0/flit_core/vendor/tomli/py.typed
--- old/flit_core-3.4.0/flit_core/vendor/tomli/py.typed 1970-01-01
01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli/py.typed 2021-12-27
14:04:58.927610600 +0100
@@ -0,0 +1 @@
+# Marker file for PEP 561
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/flit_core-3.4.0/flit_core/vendor/tomli-1.2.3.dist-info/LICENSE
new/flit_core-3.6.0/flit_core/vendor/tomli-1.2.3.dist-info/LICENSE
--- old/flit_core-3.4.0/flit_core/vendor/tomli-1.2.3.dist-info/LICENSE
1970-01-01 01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli-1.2.3.dist-info/LICENSE
2021-12-27 14:04:58.926610500 +0100
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2021 Taneli Hukkinen
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/flit_core-3.4.0/flit_core/vendor/tomli-1.2.3.dist-info/METADATA
new/flit_core-3.6.0/flit_core/vendor/tomli-1.2.3.dist-info/METADATA
--- old/flit_core-3.4.0/flit_core/vendor/tomli-1.2.3.dist-info/METADATA
1970-01-01 01:00:00.000000000 +0100
+++ new/flit_core-3.6.0/flit_core/vendor/tomli-1.2.3.dist-info/METADATA
2021-12-27 14:04:58.926610500 +0100
@@ -0,0 +1,208 @@
+Metadata-Version: 2.1
+Name: tomli
+Version: 1.2.3
+Summary: A lil' TOML parser
+Keywords: toml
+Author-email: Taneli Hukkinen <[email protected]>
+Requires-Python: >=3.6
+Description-Content-Type: text/markdown
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: MacOS
+Classifier: Operating System :: Microsoft :: Windows
+Classifier: Operating System :: POSIX :: Linux
+Classifier: Programming Language :: Python :: 3 :: Only
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Typing :: Typed
+Project-URL: Changelog,
https://github.com/hukkin/tomli/blob/master/CHANGELOG.md
+Project-URL: Homepage, https://github.com/hukkin/tomli
+
+[](https://github.com/hukkin/tomli/actions?query=workflow%3ATests+branch%3Amaster+event%3Apush)
+[](https://codecov.io/gh/hukkin/tomli)
+[](https://pypi.org/project/tomli)
+
+# Tomli
+
+> A lil' TOML parser
+
+**Table of Contents** *generated with
[mdformat-toc](https://github.com/hukkin/mdformat-toc)*
+
+<!-- mdformat-toc start --slug=github --maxlevel=6 --minlevel=2 -->
+
+- [Intro](#intro)
+- [Installation](#installation)
+- [Usage](#usage)
+ - [Parse a TOML string](#parse-a-toml-string)
+ - [Parse a TOML file](#parse-a-toml-file)
+ - [Handle invalid TOML](#handle-invalid-toml)
+ - [Construct `decimal.Decimal`s from TOML
floats](#construct-decimaldecimals-from-toml-floats)
+- [FAQ](#faq)
+ - [Why this parser?](#why-this-parser)
+ - [Is comment preserving round-trip parsing
supported?](#is-comment-preserving-round-trip-parsing-supported)
+ - [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)
+
+<!-- mdformat-toc end -->
+
+## Intro<a name="intro"></a>
+
+Tomli is a Python library for parsing [TOML](https://toml.io).
+Tomli is fully compatible with [TOML v1.0.0](https://toml.io/en/v1.0.0).
+
+## Installation<a name="installation"></a>
+
+```bash
+pip install tomli
+```
+
+## Usage<a name="usage"></a>
+
+### Parse a TOML string<a name="parse-a-toml-string"></a>
+
+```python
+import tomli
+
+toml_str = """
+ gretzky = 99
+
+ [kurri]
+ jari = 17
+ """
+
+toml_dict = tomli.loads(toml_str)
+assert toml_dict == {"gretzky": 99, "kurri": {"jari": 17}}
+```
+
+### Parse a TOML file<a name="parse-a-toml-file"></a>
+
+```python
+import tomli
+
+with open("path_to_file/conf.toml", "rb") as f:
+ toml_dict = tomli.load(f)
+```
+
+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>
+
+```python
+import tomli
+
+try:
+ toml_dict = tomli.loads("]] this is invalid TOML [[")
+except tomli.TOMLDecodeError:
+ print("Yep, definitely not valid.")
+```
+
+Note that while the `TOMLDecodeError` type is public API, error messages of
raised instances of it are not.
+Error messages should not be assumed to stay constant across Tomli versions.
+
+### Construct `decimal.Decimal`s from TOML floats<a
name="construct-decimaldecimals-from-toml-floats"></a>
+
+```python
+from decimal import Decimal
+import tomli
+
+toml_dict = tomli.loads("precision-matters = 0.982492", parse_float=Decimal)
+assert toml_dict["precision-matters"] == Decimal("0.982492")
+```
+
+Note that `decimal.Decimal` can be replaced with another callable that
converts a TOML float from string to a Python type.
+The `decimal.Decimal` is, however, a practical choice for use cases where
float inaccuracies can not be tolerated.
+
+Illegal types include `dict`, `list`, and anything that has the `append`
attribute.
+Parsing floats into an illegal type results in undefined behavior.
+
+## FAQ<a name="faq"></a>
+
+### Why this parser?<a name="why-this-parser"></a>
+
+- it's lil'
+- pure Python with zero dependencies
+- the fastest pure Python parser [\*](#performance):
+ 15x as fast as [tomlkit](https://pypi.org/project/tomlkit/),
+ 2.4x 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
+ [a test set](https://github.com/toml-lang/compliance/pull/8)
+ soon to be merged to the official
+ [compliance tests for TOML](https://github.com/toml-lang/compliance)
+ repository
+- thoroughly tested: 100% branch coverage
+
+### Is comment preserving round-trip parsing supported?<a
name="is-comment-preserving-round-trip-parsing-supported"></a>
+
+No.
+
+The `tomli.loads` function returns a plain `dict` that is populated with
builtin types and types from the standard library only.
+Preserving comments requires a custom type to be returned so will not be
supported,
+at least not by the `tomli.loads` and `tomli.load` functions.
+
+Look into [TOML Kit](https://github.com/sdispater/tomlkit) if preservation of
style is what you need.
+
+### Is there a `dumps`, `write` or `encode` function?<a
name="is-there-a-dumps-write-or-encode-function"></a>
+
+[Tomli-W](https://github.com/hukkin/tomli-w) is the write-only counterpart of
Tomli, providing `dump` and `dumps` functions.
+
+The core library does not include write capability, as most TOML use cases are
read-only, and Tomli intends to be minimal.
+
+### How do TOML types map into Python types?<a
name="how-do-toml-types-map-into-python-types"></a>
+
+| TOML type | Python type | Details
|
+| ---------------- | ------------------- |
------------------------------------------------------------ |
+| Document Root | `dict` |
|
+| Key | `str` |
|
+| String | `str` |
|
+| Integer | `int` |
|
+| Float | `float` |
|
+| Boolean | `bool` |
|
+| Offset Date-Time | `datetime.datetime` | `tzinfo` attribute set to an
instance of `datetime.timezone` |
+| Local Date-Time | `datetime.datetime` | `tzinfo` attribute set to `None`
|
+| Local Date | `datetime.date` |
|
+| Local Time | `datetime.time` |
|
+| Array | `list` |
|
+| Table | `dict` |
|
+| Inline Table | `dict` |
|
+
+## Performance<a name="performance"></a>
+
+The `benchmark/` folder in this repository contains a performance benchmark
for comparing the various Python TOML parsers.
+The benchmark can be run with `tox -e benchmark-pypi`.
+Running the benchmark on my personal computer output the following:
+
+```console
+foo@bar:~/dev/tomli$ tox -e benchmark-pypi
+benchmark-pypi installed:
attrs==19.3.0,click==7.1.2,pytomlpp==1.0.2,qtoml==0.3.0,rtoml==0.7.0,toml==0.10.2,tomli==1.1.0,tomlkit==0.7.2
+benchmark-pypi run-test-pre: PYTHONHASHSEED='2658546909'
+benchmark-pypi run-test: commands[0] | python -c 'import datetime;
print(datetime.date.today())'
+2021-07-23
+benchmark-pypi run-test: commands[1] | python --version
+Python 3.8.10
+benchmark-pypi run-test: commands[2] | python benchmark/run.py
+Parsing data.toml 5000 times:
+------------------------------------------------------
+ parser | exec time | performance (more is better)
+-----------+------------+-----------------------------
+ rtoml | 0.901 s | baseline (100%)
+ pytomlpp | 1.08 s | 83.15%
+ tomli | 3.89 s | 23.15%
+ toml | 9.36 s | 9.63%
+ qtoml | 11.5 s | 7.82%
+ tomlkit | 56.8 s | 1.59%
+```
+
+The parsers are ordered from fastest to slowest, using the fastest parser as
baseline.
+Tomli performed the best out of all pure Python TOML parsers,
+losing only to pytomlpp (wraps C++) and rtoml (wraps Rust).
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/flit_core-3.4.0/pyproject.toml
new/flit_core-3.6.0/pyproject.toml
--- old/flit_core-3.4.0/pyproject.toml 2021-05-09 17:40:19.109348300 +0200
+++ new/flit_core-3.6.0/pyproject.toml 2021-12-27 14:04:58.928610600 +0100
@@ -1,4 +1,21 @@
[build-system]
requires = []
-build-backend = "flit_core.build_thyself"
+build-backend = "flit_core.buildapi"
backend-path = ["."]
+
+[project]
+name="flit_core"
+authors=[
+ {name = "Thomas Kluyver & contributors", email = "[email protected]"},
+]
+description = "Distribution-building parts of Flit. See flit package for more
information"
+dependencies = []
+requires-python = '>=3.6'
+classifiers = [
+ "License :: OSI Approved :: BSD License",
+ "Topic :: Software Development :: Libraries :: Python Modules",
+]
+dynamic = ["version"]
+
+[project.urls]
+Source = "https://github.com/pypa/flit"