summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setuptools/_core_metadata.py21
-rw-r--r--setuptools/monkey.py4
2 files changed, 24 insertions, 1 deletions
diff --git a/setuptools/_core_metadata.py b/setuptools/_core_metadata.py
index 4b25b2f4..b8290f50 100644
--- a/setuptools/_core_metadata.py
+++ b/setuptools/_core_metadata.py
@@ -3,9 +3,12 @@ Handling of Core Metadata for Python packages (including reading and writing).
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
@@ -122,6 +125,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 23a5832d..5154d4c7 100644
--- a/setuptools/monkey.py
+++ b/setuptools/monkey.py
@@ -100,7 +100,9 @@ def patch_all():
def _patch_distribution_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(setuptools._core_metadata, attr)
setattr(distutils.dist.DistributionMetadata, attr, new_val)