|
@@ -0,0 +1,112 @@
|
|
|
+#!/usr/bin/env python3
|
|
|
+from __future__ import annotations
|
|
|
+
|
|
|
+import argparse
|
|
|
+import configparser
|
|
|
+import os.path
|
|
|
+import stat
|
|
|
+import sys
|
|
|
+import sysconfig
|
|
|
+
|
|
|
+
|
|
|
+def main() -> int:
|
|
|
+ parser = argparse.ArgumentParser()
|
|
|
+ parser.add_argument("--path", default=".")
|
|
|
+ args = parser.parse_args()
|
|
|
+
|
|
|
+ # simulate `pip install -e .` -- but bypass setuptools
|
|
|
+
|
|
|
+ def r(p: str) -> str:
|
|
|
+ return os.path.relpath(p, ".")
|
|
|
+
|
|
|
+ # must be in a virtualenv
|
|
|
+ assert not sys.flags.no_site, sys.flags.no_site
|
|
|
+ site_dir = sysconfig.get_path("purelib")
|
|
|
+ bin_dir = sysconfig.get_path("scripts")
|
|
|
+ assert "/.venv/" in site_dir, site_dir
|
|
|
+
|
|
|
+ cfg = configparser.RawConfigParser()
|
|
|
+ cfg.read(os.path.join(args.path, "setup.cfg"))
|
|
|
+
|
|
|
+ package_name = cfg["metadata"]["name"]
|
|
|
+
|
|
|
+ package_dir = cfg["options"].get("package_dir", "").strip()
|
|
|
+ if package_dir not in {"", "=src"}:
|
|
|
+ raise SystemExit(f"unsupported package_dir={package_dir!r}")
|
|
|
+
|
|
|
+ project_root = os.path.abspath(args.path)
|
|
|
+ if package_dir == "=src":
|
|
|
+ source_root = os.path.join(project_root, "src")
|
|
|
+ project_root_relative = "../"
|
|
|
+ else:
|
|
|
+ source_root = project_root
|
|
|
+ project_root_relative = "."
|
|
|
+
|
|
|
+ # egg-link indicates that the software is installed
|
|
|
+ egg_link = os.path.join(site_dir, f"{package_name}.egg-link")
|
|
|
+ print(f"writing {r(egg_link)}...")
|
|
|
+ with open(egg_link, "w") as f:
|
|
|
+ f.write(f"{source_root}\n{project_root_relative}")
|
|
|
+
|
|
|
+ # easy-install.pth is how code gets imported
|
|
|
+ easy_install_pth = os.path.join(site_dir, "easy-install.pth")
|
|
|
+ print(f"adding {r(source_root)} to {r(easy_install_pth)}...")
|
|
|
+ try:
|
|
|
+ with open(easy_install_pth) as f:
|
|
|
+ easy_install_paths = f.read().splitlines()
|
|
|
+ except OSError:
|
|
|
+ easy_install_paths = []
|
|
|
+ if source_root not in easy_install_paths:
|
|
|
+ easy_install_paths.append(source_root)
|
|
|
+ with open(easy_install_pth, "w") as f:
|
|
|
+ f.write("\n".join(easy_install_paths) + "\n")
|
|
|
+
|
|
|
+ # 0. create bin scripts for anything in `console_scripts`
|
|
|
+ console_scripts = cfg["options.entry_points"]["console_scripts"].strip()
|
|
|
+ for line in console_scripts.splitlines():
|
|
|
+ entry, rest = line.split(" = ")
|
|
|
+ mod, attr = rest.split(":")
|
|
|
+
|
|
|
+ binary = os.path.join(bin_dir, entry)
|
|
|
+ print(f"writing {r(binary)}...")
|
|
|
+ with open(binary, "w") as f:
|
|
|
+ f.write(
|
|
|
+ f"#!{sys.executable}\n"
|
|
|
+ f"from {mod} import {attr}\n"
|
|
|
+ f'if __name__ == "__main__":\n'
|
|
|
+ f" raise SystemExit({attr}())\n"
|
|
|
+ )
|
|
|
+ mode = os.stat(binary).st_mode
|
|
|
+ mode |= stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH
|
|
|
+ os.chmod(binary, mode)
|
|
|
+
|
|
|
+ # 0. write out the `sentry.egg-info` directory in `src/`
|
|
|
+ egg_info_dir = os.path.join(source_root, f"{package_name}.egg-info")
|
|
|
+ print(f"creating {r(egg_info_dir)}...")
|
|
|
+ os.makedirs(egg_info_dir, exist_ok=True)
|
|
|
+
|
|
|
+ entry_points_txt = os.path.join(egg_info_dir, "entry_points.txt")
|
|
|
+ print(f"writing {r(entry_points_txt)}...")
|
|
|
+ ep_cfg = configparser.RawConfigParser()
|
|
|
+ for section, eps in cfg["options.entry_points"].items():
|
|
|
+ ep_cfg.add_section(section)
|
|
|
+ for ep in eps.strip().splitlines():
|
|
|
+ k, v = ep.split(" = ")
|
|
|
+ ep_cfg[section][k] = v
|
|
|
+ with open(entry_points_txt, "w") as f:
|
|
|
+ ep_cfg.write(f)
|
|
|
+
|
|
|
+ pkg_info = os.path.join(egg_info_dir, "PKG-INFO")
|
|
|
+ print(f"writing {r(pkg_info)}...")
|
|
|
+ with open(pkg_info, "w") as f:
|
|
|
+ f.write(
|
|
|
+ f"Metadata-Version: 2.1\n"
|
|
|
+ f"Name: {package_name}\n"
|
|
|
+ f"Version: {cfg['metadata']['version']}\n"
|
|
|
+ )
|
|
|
+
|
|
|
+ return 0
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ raise SystemExit(main())
|