| 10 | |
| 11 | |
| 12 | def main() -> int: |
| 13 | parser = argparse.ArgumentParser() |
| 14 | parser.add_argument("--path", default=".") |
| 15 | args = parser.parse_args() |
| 16 | |
| 17 | # simulate `pip install -e .` -- but bypass setuptools |
| 18 | |
| 19 | def r(p: str) -> str: |
| 20 | return os.path.relpath(p, ".") |
| 21 | |
| 22 | # must be in a virtualenv |
| 23 | assert not sys.flags.no_site, sys.flags.no_site |
| 24 | site_dir = sysconfig.get_path("purelib") |
| 25 | bin_dir = sysconfig.get_path("scripts") |
| 26 | assert "/.venv/" in site_dir, site_dir |
| 27 | |
| 28 | cfg = configparser.RawConfigParser() |
| 29 | cfg.read(os.path.join(args.path, "setup.cfg")) |
| 30 | |
| 31 | package_name = cfg["metadata"]["name"] |
| 32 | |
| 33 | package_dir = cfg["options"].get("package_dir", "").strip() |
| 34 | if package_dir not in {"", "=src"}: |
| 35 | raise SystemExit(f"unsupported package_dir={package_dir!r}") |
| 36 | |
| 37 | project_root = os.path.abspath(args.path) |
| 38 | if package_dir == "=src": |
| 39 | source_root = os.path.join(project_root, "src") |
| 40 | project_root_relative = "../" |
| 41 | else: |
| 42 | source_root = project_root |
| 43 | project_root_relative = "." |
| 44 | |
| 45 | # egg-link indicates that the software is installed |
| 46 | egg_link = os.path.join(site_dir, f"{package_name}.egg-link") |
| 47 | print(f"writing {r(egg_link)}...") |
| 48 | with open(egg_link, "w") as f: |
| 49 | f.write(f"{source_root}\n{project_root_relative}") |
| 50 | |
| 51 | # easy-install.pth is how code gets imported |
| 52 | easy_install_pth = os.path.join(site_dir, "easy-install.pth") |
| 53 | print(f"adding {r(source_root)} to {r(easy_install_pth)}...") |
| 54 | try: |
| 55 | with open(easy_install_pth) as f: |
| 56 | easy_install_paths = f.read().splitlines() |
| 57 | except OSError: |
| 58 | easy_install_paths = [] |
| 59 | if source_root not in easy_install_paths: |
| 60 | easy_install_paths.append(source_root) |
| 61 | with open(easy_install_pth, "w") as f: |
| 62 | f.write("\n".join(easy_install_paths) + "\n") |
| 63 | |
| 64 | # 0. create bin scripts for anything in `console_scripts` |
| 65 | console_scripts = cfg["options.entry_points"]["console_scripts"].strip() |
| 66 | for line in console_scripts.splitlines(): |
| 67 | entry, rest = line.split(" = ") |
| 68 | mod, attr = rest.split(":") |
| 69 | |