Mercurial > hgrepos > Python > apps > py-cutils
comparison _postprocess-sdist.py @ 284:b65d25882e44
REFACTOR: sdist generation: postprocess an sdist to include symbolic links as symbolic links.
A standard sdist contains no symlinks but dereferences symlinks encountered
in the source tree.
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sun, 23 Feb 2025 21:27:48 +0100 |
| parents | |
| children | 39a19c008708 |
comparison
equal
deleted
inserted
replaced
| 283:99b78fa04bc1 | 284:b65d25882e44 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 """Postprogress a .tar-sdist to include tests/data with symlinks as symlinks | |
| 3 | |
| 4 """ | |
| 5 | |
| 6 from __future__ import print_function, absolute_import | |
| 7 | |
| 8 import ast | |
| 9 try: | |
| 10 from configparser import ConfigParser | |
| 11 except ImportError: | |
| 12 from ConfigParser import SafeConfigParser as ConfigParser | |
| 13 import io | |
| 14 import os | |
| 15 import tarfile | |
| 16 | |
| 17 import cutils | |
| 18 import cutils.util.walk | |
| 19 | |
| 20 | |
| 21 def main(): | |
| 22 with io.open("setup.cfg", "rt", encoding="utf-8") as cfgfile: | |
| 23 cp = ConfigParser() | |
| 24 if hasattr(cp, "read_file"): | |
| 25 cp.read_file(cfgfile, "setup.cfg") | |
| 26 else: | |
| 27 cp.readfp(cfgfile, "setup.cfg") | |
| 28 project_name = cp.get("metadata", "name") | |
| 29 project_version = cp.get("metadata", "version") | |
| 30 if project_version.startswith("attr:"): | |
| 31 assert project_version == "attr: cutils.__version__" | |
| 32 project_version = ast.literal_eval(repr(cutils.__version__)) | |
| 33 # | |
| 34 # Compressed tar files cannot be modified by Python: make sure the | |
| 35 # originally generated archive is uncompressed. | |
| 36 # | |
| 37 assert cp.get("sdist", "formats") == "tar" | |
| 38 | |
| 39 archive_name = "{}-{}.tar".format(project_name, project_version) | |
| 40 archive_path = "dist/" + archive_name | |
| 41 assert os.path.isfile(archive_path) | |
| 42 | |
| 43 # the directory within the archive | |
| 44 archive_path_prefix = "{}-{}".format(project_name, project_version) | |
| 45 | |
| 46 egg_directory = "{}.egg-info".format(project_name.replace("-", "_")) | |
| 47 assert os.path.isdir(egg_directory) | |
| 48 sources_txt_path = "{}/SOURCES.txt".format(egg_directory) | |
| 49 sources_txt_arcname = "{}/{}/SOURCES.txt".format( | |
| 50 archive_path_prefix, | |
| 51 egg_directory) | |
| 52 | |
| 53 with tarfile.TarFile(archive_path, "r") as tf: | |
| 54 sf = tf.extractfile(sources_txt_arcname) | |
| 55 try: | |
| 56 sources_txt = sf.read() | |
| 57 finally: | |
| 58 sf.close() | |
| 59 | |
| 60 with tarfile.TarFile(archive_path, "a") as tf: | |
| 61 arcname = "{}/tests/data".format(archive_path_prefix) | |
| 62 try: | |
| 63 info = tf.getmember(arcname) | |
| 64 except KeyError: | |
| 65 pass | |
| 66 else: | |
| 67 raise RuntimeError("already postprocessed") | |
| 68 pre_names = set(tf.getnames()) | |
| 69 tf.add("tests/data", arcname=arcname, recursive=True) | |
| 70 | |
| 71 # | |
| 72 # Determine the new files and symlinks that are to be added | |
| 73 # to SOURCES.txt. Skip directories. | |
| 74 # | |
| 75 post_names = set(tf.getnames()) | |
| 76 new_names = list(post_names - pre_names) | |
| 77 new_names.sort() | |
| 78 new_sources = [] | |
| 79 | |
| 80 for np in new_names: | |
| 81 nn = np[len(archive_path_prefix)+1:] | |
| 82 info = tf.getmember(np) | |
| 83 if not info.isdir(): | |
| 84 new_sources.append(nn) | |
| 85 | |
| 86 # Augment SOURCES.txt and add it to the archive | |
| 87 sources_info = tf.gettarinfo( | |
| 88 sources_txt_path, arcname=sources_txt_arcname) | |
| 89 sf = io.BytesIO() | |
| 90 sf.write(sources_txt) | |
| 91 if not sources_txt.endswith(b'\n'): | |
| 92 sf.write(b'\n') | |
| 93 sf.write(b('\n'.join(new_sources))) | |
| 94 sources_info.size = len(sf.getvalue()) | |
| 95 sf.seek(0) | |
| 96 tf.addfile(sources_info, sf) | |
| 97 | |
| 98 | |
| 99 def b(buf, encoding="ascii"): | |
| 100 if isinstance(buf, bytes): | |
| 101 return buf | |
| 102 else: | |
| 103 return buf.encode(encoding) | |
| 104 | |
| 105 | |
| 106 if __name__ == "__main__": | |
| 107 main() |
