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]