diff --git a/setuptools/_core_metadata.py b/setuptools/_core_metadata.py index cf940dfa1d..c1d41c6680 100644 --- a/setuptools/_core_metadata.py +++ b/setuptools/_core_metadata.py @@ -3,9 +3,12 @@ See: https://packaging.python.org/en/latest/specifications/core-metadata/ """ +import os +import stat import textwrap from email import message_from_file from email.message import Message +from tempfile import NamedTemporaryFile from typing import Optional, List from distutils.util import rfc822_escape @@ -119,6 +122,24 @@ def single_line(val): return val +def write_pkg_info(self, base_dir): + """Write the PKG-INFO file into the release tree.""" + temp = "" + final = os.path.join(base_dir, 'PKG-INFO') + try: + # Use a temporary file while writing to avoid race conditions + # (e.g. `importlib.metadata` reading `.egg-info/PKG-INFO`): + with NamedTemporaryFile("w", encoding="utf-8", dir=base_dir, delete=False) as f: + temp = f.name + self.write_pkg_file(f) + permissions = stat.S_IMODE(os.lstat(temp).st_mode) + os.chmod(temp, permissions | stat.S_IRGRP | stat.S_IROTH) + os.replace(temp, final) # atomic operation. + finally: + if temp and os.path.exists(temp): + os.remove(temp) + + # Based on Python 3.5 version def write_pkg_file(self, file): # noqa: C901 # is too complex (14) # FIXME """Write the PKG-INFO format data to a file object.""" diff --git a/setuptools/monkey.py b/setuptools/monkey.py index f0fb7ec57b..2ab98c178a 100644 --- a/setuptools/monkey.py +++ b/setuptools/monkey.py @@ -102,7 +102,12 @@ def _patch_distribution_metadata(): from . import _core_metadata """Patch write_pkg_file and read_pkg_file for higher metadata standards""" - for attr in ('write_pkg_file', 'read_pkg_file', 'get_metadata_version'): + for attr in ( + 'write_pkg_info', + 'write_pkg_file', + 'read_pkg_file', + 'get_metadata_version', + ): new_val = getattr(_core_metadata, attr) setattr(distutils.dist.DistributionMetadata, attr, new_val)