Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-hatchling for 
openSUSE:Factory checked in at 2022-10-12 18:23:11
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-hatchling (Old)
 and      /work/SRC/openSUSE:Factory/.python-hatchling.new.2275 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-hatchling"

Wed Oct 12 18:23:11 2022 rev:10 rq:1009265 version:1.11.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-hatchling/python-hatchling.changes        
2022-09-25 15:34:39.447529635 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-hatchling.new.2275/python-hatchling.changes  
    2022-10-12 18:24:04.409571832 +0200
@@ -1,0 +2,17 @@
+Sun Oct  9 19:49:17 UTC 2022 - Beno??t Monin <benoit.mo...@gmx.fr>
+
+- update to version 1.11.0:
+  * Added:
+    + Add env version source to retrieve the version from an
+      environment variable
+    + Add validate-bump option to the standard version scheme
+  * Fixed:
+    + Use proper CSV formatting for the RECORD metadata file of the
+      wheel target to avoid warnings during installation by pip if,
+      for example, file names contain commas
+    + Fix installations with pip for build hooks that modify
+      runtime dependencies
+    + Decreasing verbosity now has no affect on output that should
+      always be displayed
+
+-------------------------------------------------------------------

Old:
----
  hatchling-1.10.0.tar.gz

New:
----
  hatchling-1.11.0.tar.gz

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

Other differences:
------------------
++++++ python-hatchling.spec ++++++
--- /var/tmp/diff_new_pack.buCRYs/_old  2022-10-12 18:24:06.021575859 +0200
+++ /var/tmp/diff_new_pack.buCRYs/_new  2022-10-12 18:24:06.029575879 +0200
@@ -19,7 +19,7 @@
 %define skip_python2 1
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-hatchling
-Version:        1.10.0
+Version:        1.11.0
 Release:        0
 Summary:        Build backend used by Hatch
 License:        MIT

++++++ hatchling-1.10.0.tar.gz -> hatchling-1.11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hatchling-1.10.0/PKG-INFO 
new/hatchling-1.11.0/PKG-INFO
--- old/hatchling-1.10.0/PKG-INFO       2020-02-02 01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/PKG-INFO       2020-02-02 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: hatchling
-Version: 1.10.0
+Version: 1.11.0
 Summary: Modern, extensible Python build backend
 Project-URL: Homepage, https://hatch.pypa.io/latest/
 Project-URL: Sponsor, https://github.com/sponsors/ofek
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hatchling-1.10.0/src/hatchling/__about__.py 
new/hatchling-1.11.0/src/hatchling/__about__.py
--- old/hatchling-1.10.0/src/hatchling/__about__.py     2020-02-02 
01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/__about__.py     2020-02-02 
01:00:00.000000000 +0100
@@ -1 +1 @@
-__version__ = '1.10.0'
+__version__ = '1.11.0'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hatchling-1.10.0/src/hatchling/bridge/app.py 
new/hatchling-1.11.0/src/hatchling/bridge/app.py
--- old/hatchling-1.10.0/src/hatchling/bridge/app.py    2020-02-02 
01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/bridge/app.py    2020-02-02 
01:00:00.000000000 +0100
@@ -4,6 +4,9 @@
 
 
 class InvokedApplication:
+    def display_always(self, *args, **kwargs):
+        send_app_command('display_always', *args, **kwargs)
+
     def display_info(self, *args, **kwargs):
         send_app_command('display_info', *args, **kwargs)
 
@@ -45,6 +48,10 @@
     def __init__(self):
         self.__verbosity = int(os.environ.get('HATCH_VERBOSE', '0')) - 
int(os.environ.get('HATCH_QUIET', '0'))
 
+    def display_always(self, message='', **kwargs):
+        # Do not document
+        print(message)
+
     def display_info(self, message='', **kwargs):
         """
         Meant to be used for messages conveying basic information.
@@ -110,6 +117,7 @@
 class SafeApplication:
     def __init__(self, app):
         self.abort = app.abort
+        self.display_always = app.display_always
         self.display_info = app.display_info
         self.display_error = app.display_error
         self.display_success = app.display_success
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hatchling-1.10.0/src/hatchling/build.py 
new/hatchling-1.11.0/src/hatchling/build.py
--- old/hatchling-1.10.0/src/hatchling/build.py 2020-02-02 01:00:00.000000000 
+0100
+++ new/hatchling-1.11.0/src/hatchling/build.py 2020-02-02 01:00:00.000000000 
+0100
@@ -31,24 +31,6 @@
     return builder.config.dependencies
 
 
-def prepare_metadata_for_build_wheel(metadata_directory, config_settings=None):
-    """
-    https://peps.python.org/pep-0517/#prepare-metadata-for-build-wheel
-    """
-    from hatchling.builders.wheel import WheelBuilder
-
-    builder = WheelBuilder(os.getcwd())
-
-    directory = os.path.join(metadata_directory, 
f'{builder.artifact_project_id}.dist-info')
-    if not os.path.isdir(directory):
-        os.mkdir(directory)
-
-    with open(os.path.join(directory, 'METADATA'), 'w', encoding='utf-8') as f:
-        f.write(builder.config.core_metadata_constructor(builder.metadata))
-
-    return os.path.basename(directory)
-
-
 def build_wheel(wheel_directory, config_settings=None, 
metadata_directory=None):
     """
     https://peps.python.org/pep-0517/#build-wheel
@@ -69,28 +51,6 @@
     return builder.config.dependencies
 
 
-def prepare_metadata_for_build_editable(metadata_directory, 
config_settings=None):
-    """
-    https://peps.python.org/pep-0660/#prepare-metadata-for-build-editable
-    """
-    from hatchling.builders.wheel import EDITABLES_MINIMUM_VERSION, 
WheelBuilder
-
-    builder = WheelBuilder(os.getcwd())
-
-    directory = os.path.join(metadata_directory, 
f'{builder.artifact_project_id}.dist-info')
-    if not os.path.isdir(directory):
-        os.mkdir(directory)
-
-    extra_dependencies = []
-    if not builder.config.dev_mode_dirs and builder.config.dev_mode_exact:
-        extra_dependencies.append(f'editables~={EDITABLES_MINIMUM_VERSION}')
-
-    with open(os.path.join(directory, 'METADATA'), 'w', encoding='utf-8') as f:
-        f.write(builder.config.core_metadata_constructor(builder.metadata, 
extra_dependencies=extra_dependencies))
-
-    return os.path.basename(directory)
-
-
 def build_editable(wheel_directory, config_settings=None, 
metadata_directory=None):
     """
     https://peps.python.org/pep-0660/#build-editable
@@ -99,3 +59,56 @@
 
     builder = WheelBuilder(os.getcwd())
     return os.path.basename(next(builder.build(wheel_directory, ['editable'])))
+
+
+# Any builder that has build-time hooks like Hatchling and setuptools cannot 
technically keep PEP 517's identical
+# metadata promise e.g. C extensions would require different tags in the 
`WHEEL` file. Therefore, we consider the
+# methods as mostly being for non-frontend tools like tox and dependency 
updaters. So Hatchling only writes the
+# `METADATA` file to the metadata directory and continues to ignore that 
directory itself.
+#
+# An issue we encounter by supporting this metadata-only access is that for 
installations with pip the required
+# dependencies of the project are read at this stage. This means that build 
hooks that add to the `dependencies`
+# build data or modify the built wheel have no effect on what dependencies are 
or are not installed.
+#
+# There are legitimate use cases in which this is required, so we only define 
these when no pip build is detected.
+# See: 
https://github.com/pypa/pip/blob/22.2.2/src/pip/_internal/operations/build/build_tracker.py#L41-L51
+# Example use case: https://github.com/pypa/hatch/issues/532
+if 'PIP_BUILD_TRACKER' not in os.environ:
+
+    def prepare_metadata_for_build_wheel(metadata_directory, 
config_settings=None):
+        """
+        https://peps.python.org/pep-0517/#prepare-metadata-for-build-wheel
+        """
+        from hatchling.builders.wheel import WheelBuilder
+
+        builder = WheelBuilder(os.getcwd())
+
+        directory = os.path.join(metadata_directory, 
f'{builder.artifact_project_id}.dist-info')
+        if not os.path.isdir(directory):
+            os.mkdir(directory)
+
+        with open(os.path.join(directory, 'METADATA'), 'w', encoding='utf-8') 
as f:
+            f.write(builder.config.core_metadata_constructor(builder.metadata))
+
+        return os.path.basename(directory)
+
+    def prepare_metadata_for_build_editable(metadata_directory, 
config_settings=None):
+        """
+        https://peps.python.org/pep-0660/#prepare-metadata-for-build-editable
+        """
+        from hatchling.builders.wheel import EDITABLES_MINIMUM_VERSION, 
WheelBuilder
+
+        builder = WheelBuilder(os.getcwd())
+
+        directory = os.path.join(metadata_directory, 
f'{builder.artifact_project_id}.dist-info')
+        if not os.path.isdir(directory):
+            os.mkdir(directory)
+
+        extra_dependencies = []
+        if not builder.config.dev_mode_dirs and builder.config.dev_mode_exact:
+            
extra_dependencies.append(f'editables~={EDITABLES_MINIMUM_VERSION}')
+
+        with open(os.path.join(directory, 'METADATA'), 'w', encoding='utf-8') 
as f:
+            f.write(builder.config.core_metadata_constructor(builder.metadata, 
extra_dependencies=extra_dependencies))
+
+        return os.path.basename(directory)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hatchling-1.10.0/src/hatchling/builders/wheel.py 
new/hatchling-1.11.0/src/hatchling/builders/wheel.py
--- old/hatchling-1.10.0/src/hatchling/builders/wheel.py        2020-02-02 
01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/builders/wheel.py        2020-02-02 
01:00:00.000000000 +0100
@@ -1,9 +1,11 @@
+from __future__ import annotations
+
+import csv
 import hashlib
 import os
 import stat
 import tempfile
 import zipfile
-from contextlib import closing
 from io import StringIO
 
 from hatchling.__about__ import __version__
@@ -24,6 +26,24 @@
 EDITABLES_MINIMUM_VERSION = '0.3'
 
 
+class RecordFile:
+    def __init__(self):
+        self.__file_obj = StringIO()
+        self.__writer = csv.writer(self.__file_obj, delimiter=',', 
quotechar='"', lineterminator='\n')
+
+    def write(self, record: tuple[str, str, str]) -> None:
+        self.__writer.writerow(record)
+
+    def construct(self) -> str:
+        return self.__file_obj.getvalue()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        self.__file_obj.close()
+
+
 class WheelArchive:
     def __init__(self, project_id, reproducible):
         """
@@ -77,7 +97,7 @@
                 out_file.write(chunk)
 
         hash_digest = format_file_hash(hash_obj.digest())
-        return relative_path, hash_digest, file_stat.st_size
+        return relative_path, f'sha256={hash_digest}', str(file_stat.st_size)
 
     def write_metadata(self, relative_path, contents):
         relative_path = 
f'{self.metadata_directory}/{normalize_archive_path(relative_path)}'
@@ -105,7 +125,7 @@
         hash_digest = format_file_hash(hash_obj.digest())
         self.zf.writestr(zip_info, contents, 
compress_type=zipfile.ZIP_DEFLATED)
 
-        return relative_path, hash_digest, len(contents)
+        return relative_path, f'sha256={hash_digest}', str(len(contents))
 
     def __enter__(self):
         return self
@@ -306,17 +326,15 @@
             else:
                 build_data['tag'] = self.get_default_tag()
 
-        with WheelArchive(self.artifact_project_id, self.config.reproducible) 
as archive, closing(
-            StringIO()
-        ) as records:
+        with WheelArchive(self.artifact_project_id, self.config.reproducible) 
as archive, RecordFile() as records:
             for included_file in self.recurse_included_files():
                 record = archive.add_file(included_file)
-                records.write(self.format_record(record))
+                records.write(record)
 
             self.write_data(archive, records, build_data, 
build_data['dependencies'])
 
-            records.write(f'{archive.metadata_directory}/RECORD,,\n')
-            archive.write_metadata('RECORD', records.getvalue())
+            records.write((f'{archive.metadata_directory}/RECORD', '', ''))
+            archive.write_metadata('RECORD', records.construct())
 
         target = os.path.join(directory, 
f"{self.artifact_project_id}-{build_data['tag']}.whl")
 
@@ -334,9 +352,7 @@
 
         build_data['tag'] = self.get_default_tag()
 
-        with WheelArchive(self.artifact_project_id, self.config.reproducible) 
as archive, closing(
-            StringIO()
-        ) as records:
+        with WheelArchive(self.artifact_project_id, self.config.reproducible) 
as archive, RecordFile() as records:
             exposed_packages = {}
             for included_file in self.recurse_project_files():
                 if not included_file.path.endswith('.py'):
@@ -380,11 +396,11 @@
 
             for filename, content in sorted(editable_project.files()):
                 record = archive.write_file(filename, content)
-                records.write(self.format_record(record))
+                records.write(record)
 
             for included_file in 
self.recurse_forced_files(self.get_forced_inclusion_map(build_data)):
                 record = archive.add_file(included_file)
-                records.write(self.format_record(record))
+                records.write(record)
 
             extra_dependencies = list(build_data['dependencies'])
             for dependency in editable_project.dependencies():
@@ -397,8 +413,8 @@
 
             self.write_data(archive, records, build_data, extra_dependencies)
 
-            records.write(f'{archive.metadata_directory}/RECORD,,\n')
-            archive.write_metadata('RECORD', records.getvalue())
+            records.write((f'{archive.metadata_directory}/RECORD', '', ''))
+            archive.write_metadata('RECORD', records.construct())
 
         target = os.path.join(directory, 
f"{self.artifact_project_id}-{build_data['tag']}.whl")
 
@@ -408,25 +424,23 @@
     def build_editable_explicit(self, directory, **build_data):
         build_data['tag'] = self.get_default_tag()
 
-        with WheelArchive(self.artifact_project_id, self.config.reproducible) 
as archive, closing(
-            StringIO()
-        ) as records:
+        with WheelArchive(self.artifact_project_id, self.config.reproducible) 
as archive, RecordFile() as records:
             directories = sorted(
                 os.path.normpath(os.path.join(self.root, relative_directory))
                 for relative_directory in self.config.dev_mode_dirs
             )
 
             record = 
archive.write_file(f"{self.metadata.core.name.replace('-', '_')}.pth", 
'\n'.join(directories))
-            records.write(self.format_record(record))
+            records.write(record)
 
             for included_file in 
self.recurse_forced_files(self.get_forced_inclusion_map(build_data)):
                 record = archive.add_file(included_file)
-                records.write(self.format_record(record))
+                records.write(record)
 
             self.write_data(archive, records, build_data, 
build_data['dependencies'])
 
-            records.write(f'{archive.metadata_directory}/RECORD,,\n')
-            archive.write_metadata('RECORD', records.getvalue())
+            records.write((f'{archive.metadata_directory}/RECORD', '', ''))
+            archive.write_metadata('RECORD', records.construct())
 
         target = os.path.join(directory, 
f"{self.artifact_project_id}-{build_data['tag']}.whl")
 
@@ -442,7 +456,7 @@
     def add_shared_data(self, archive, records):
         for shared_file in 
self.recurse_explicit_files(self.config.shared_data):
             record = archive.add_shared_file(shared_file)
-            records.write(self.format_record(record))
+            records.write(record)
 
     def write_metadata(self, archive, records, build_data, 
extra_dependencies=()):
         # <<< IMPORTANT >>>
@@ -476,31 +490,31 @@
             metadata += f'Tag: {tag}\n'
 
         record = archive.write_metadata('WHEEL', metadata)
-        records.write(self.format_record(record))
+        records.write(record)
 
     def write_entry_points_file(self, archive, records):
         entry_points_file = self.construct_entry_points_file()
         if entry_points_file:
             record = archive.write_metadata('entry_points.txt', 
entry_points_file)
-            records.write(self.format_record(record))
+            records.write(record)
 
     def write_project_metadata(self, archive, records, extra_dependencies=()):
         record = archive.write_metadata(
             'METADATA', self.config.core_metadata_constructor(self.metadata, 
extra_dependencies=extra_dependencies)
         )
-        records.write(self.format_record(record))
+        records.write(record)
 
     def add_licenses(self, archive, records):
         for relative_path in self.metadata.core.license_files:
             license_file = os.path.normpath(os.path.join(self.root, 
relative_path))
             with open(license_file, 'rb') as f:
                 record = archive.write_metadata(f'licenses/{relative_path}', 
f.read())
-                records.write(self.format_record(record))
+                records.write(record)
 
     def add_extra_metadata(self, archive, records):
         for extra_metadata_file in 
self.recurse_explicit_files(self.config.extra_metadata):
             record = archive.add_extra_metadata_file(extra_metadata_file)
-            records.write(self.format_record(record))
+            records.write(record)
 
     def construct_entry_points_file(self):
         core_metadata = self.metadata.core
@@ -554,7 +568,3 @@
     @classmethod
     def get_config_class(cls):
         return WheelBuilderConfig
-
-    @staticmethod
-    def format_record(record):
-        return '{},sha256={},{}\n'.format(*record)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hatchling-1.10.0/src/hatchling/cli/metadata/__init__.py 
new/hatchling-1.11.0/src/hatchling/cli/metadata/__init__.py
--- old/hatchling-1.10.0/src/hatchling/cli/metadata/__init__.py 2020-02-02 
01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/cli/metadata/__init__.py 2020-02-02 
01:00:00.000000000 +0100
@@ -21,11 +21,11 @@
         if field not in metadata:
             app.abort(f'Unknown metadata field: {field}')
         elif field == 'readme':
-            app.display_info(metadata[field]['text'])
+            app.display_always(metadata[field]['text'])
         elif isinstance(metadata[field], str):
-            app.display_info(metadata[field])
+            app.display_always(metadata[field])
         else:
-            app.display_info(json.dumps(metadata[field], indent=4))
+            app.display_always(json.dumps(metadata[field], indent=4))
 
         return
 
@@ -34,9 +34,9 @@
             metadata.pop(key)
 
     if compact:
-        app.display_info(json.dumps(metadata, separators=(',', ':')))
+        app.display_always(json.dumps(metadata, separators=(',', ':')))
     else:  # no cov
-        app.display_info(json.dumps(metadata, indent=4))
+        app.display_always(json.dumps(metadata, indent=4))
 
 
 def metadata_command(subparsers, defaults):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hatchling-1.10.0/src/hatchling/cli/version/__init__.py 
new/hatchling-1.11.0/src/hatchling/cli/version/__init__.py
--- old/hatchling-1.10.0/src/hatchling/cli/version/__init__.py  2020-02-02 
01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/cli/version/__init__.py  2020-02-02 
01:00:00.000000000 +0100
@@ -18,7 +18,7 @@
         if desired_version:
             app.abort('Cannot set version when it is statically defined by the 
`project.version` field')
         else:
-            app.display_info(app.project.metadata.core.version)
+            app.display_always(app.project.metadata.core.version)
             return
 
     source = metadata.hatch.version.source
@@ -27,7 +27,7 @@
     original_version = version_data['version']
 
     if not desired_version:
-        app.display_info(original_version)
+        app.display_always(original_version)
         return
 
     updated_version = metadata.hatch.version.scheme.update(desired_version, 
original_version, version_data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hatchling-1.10.0/src/hatchling/version/scheme/standard.py 
new/hatchling-1.11.0/src/hatchling/version/scheme/standard.py
--- old/hatchling-1.10.0/src/hatchling/version/scheme/standard.py       
2020-02-02 01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/version/scheme/standard.py       
2020-02-02 01:00:00.000000000 +0100
@@ -44,7 +44,7 @@
                     raise ValueError('Cannot specify multiple update 
operations with an explicit version')
 
                 next_version = Version(version)
-                if next_version <= original:
+                if self.config.get('validate-bump', True) and next_version <= 
original:
                     raise ValueError(
                         f'Version `{version}` is not higher than the original 
version `{original_version}`'
                     )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hatchling-1.10.0/src/hatchling/version/source/env.py 
new/hatchling-1.11.0/src/hatchling/version/source/env.py
--- old/hatchling-1.10.0/src/hatchling/version/source/env.py    1970-01-01 
01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/version/source/env.py    2020-02-02 
01:00:00.000000000 +0100
@@ -0,0 +1,22 @@
+import os
+
+from hatchling.version.source.plugin.interface import VersionSourceInterface
+
+
+class EnvSource(VersionSourceInterface):
+    PLUGIN_NAME = 'env'
+
+    def get_version_data(self):
+        variable = self.config.get('variable', '')
+        if not variable:
+            raise ValueError('option `variable` must be specified')
+        elif not isinstance(variable, str):
+            raise TypeError('option `variable` must be a string')
+
+        if variable not in os.environ:
+            raise RuntimeError(f'environment variable `{variable}` is not set')
+
+        return {'version': os.environ[variable]}
+
+    def set_version(self, version, version_data):
+        raise NotImplementedError('Cannot set environment variables')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/hatchling-1.10.0/src/hatchling/version/source/plugin/hooks.py 
new/hatchling-1.11.0/src/hatchling/version/source/plugin/hooks.py
--- old/hatchling-1.10.0/src/hatchling/version/source/plugin/hooks.py   
2020-02-02 01:00:00.000000000 +0100
+++ new/hatchling-1.11.0/src/hatchling/version/source/plugin/hooks.py   
2020-02-02 01:00:00.000000000 +0100
@@ -1,8 +1,9 @@
 from hatchling.plugin import hookimpl
 from hatchling.version.source.code import CodeSource
+from hatchling.version.source.env import EnvSource
 from hatchling.version.source.regex import RegexSource
 
 
 @hookimpl
 def hatch_register_version_source():
-    return [CodeSource, RegexSource]
+    return [CodeSource, EnvSource, RegexSource]

Reply via email to