From 984b3107759c4cdaef9d18ede2a7649954e17d0f Mon Sep 17 00:00:00 2001 From: Jean-Christophe Morin Date: Sun, 17 Sep 2023 16:41:18 -0400 Subject: [PATCH] Adapt setup.py to add entry-points in dist-info.data/scripts/rez Signed-off-by: Jean-Christophe Morin --- .github/workflows/wheel.yaml | 54 +++++++++++++++++++++++- pyproject.toml | 3 ++ setup.py | 68 +++++++++++++++++++++++++++++-- src/rez/cli/_entry_points.py | 79 ++++++++++++++++++++---------------- 4 files changed, 163 insertions(+), 41 deletions(-) create mode 100644 pyproject.toml diff --git a/.github/workflows/wheel.yaml b/.github/workflows/wheel.yaml index fe4d9bbb93..13e46aea49 100644 --- a/.github/workflows/wheel.yaml +++ b/.github/workflows/wheel.yaml @@ -36,4 +36,56 @@ jobs: cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release VERBOSE=1 cmake --build . - ls -la + mv simple_launcher_cli.exe t64.exe + mv simple_launcher_gui.exe w64.exe + + - uses: actions/upload-artifact@v3 + with: + name: launchers + path: 'launcher/build/*.exe' + + wheel: + name: Build wheel + needs: ["launchers"] + runs-on: "windows-latest" + + steps: + - uses: actions/checkout@v4 + + - uses: actions/download-artifact@v3 + with: + name: launchers + path: launcher + + - uses: actions/setup-python@v4 + with: + python-version: 3.11 + + - name: Build wheel + shell: bash + run: | + set -ex + python -m pip install build + python -m build -w . + + - name: Install wheel + shell: bash + run: | + set -ex + python -m venv .venv + .venv/Scripts/python.exe -m pip install dist/* + ls -la .venv/Scripts/ + ls -la .venv/Scripts/rez + + - name: Test commands + shell: bash + run: | + export PATH=$(pwd)/.venv/Scripts/rez:$PATH + set -ex + cat .venv/Scripts/rez/rez-script.py + cat .venv/Scripts/rez/jctest-script.py + jctest + + rez --help + rez --version + rez-env --help diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000..fed528d4a7 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,3 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index fc936c2937..07d5eb58a2 100644 --- a/setup.py +++ b/setup.py @@ -8,10 +8,15 @@ import os import os.path import sys +import logging +import tempfile +import platform +import shutil try: from setuptools import setup, find_packages + import distutils.command.build_scripts except ImportError: print("install failed - requires setuptools", file=sys.stderr) sys.exit(1) @@ -51,6 +56,62 @@ def find_files(pattern, path=None, root="rez"): long_description = f.read() +SCRIPT_TEMPLATE = """#!/usr/bin/python -E +# -*- coding: utf-8 -*- +import re +import sys +from rez.cli._entry_points import {0} +if __name__ == '__main__': + sys.argv[0] = re.sub(r'(-script\\.pyw|\\.exe)?$', '', sys.argv[0]) + sys.exit({0}()) +""" + +class build_scripts(distutils.command.build_scripts.build_scripts): + def finalize_options(self): + super().finalize_options() + self.build_dir = os.path.join(self.build_dir, "rez") + + def run(self): + logging.getLogger().info("running rez's customized build_scripts command") + + scripts = [] + tmpdir = tempfile.mkdtemp("rez-scripts") + + os.makedirs(self.build_dir) + + for command in self.scripts: + spec = get_specifications()[command] + + filename = "{0}.py".format(command) + if platform.system() == "Windows": + filename = "{0}-script.py".format(command) + + path = os.path.join(tmpdir, filename) + with open(path, "w") as fd: + fd.write(SCRIPT_TEMPLATE.format(spec["func"])) + + scripts.append(path) + + if platform.system() == "Windows": + launcher = "t64.exe" + if spec["type"] == "window": + launcher = "w64.exe" + + self.copy_file( + os.path.join("launcher", launcher), + os.path.join(self.build_dir, "{0}.exe".format(command)) + ) + + prod_install_path = os.path.join(tmpdir, ".rez_production_install") + with open(prod_install_path, "w") as fd: + fd.write("# Production install installed with pip") + + scripts.append(prod_install_path) + + self.scripts = scripts + return super().run() + + setup( name="rez", version=_rez_version, @@ -65,9 +126,7 @@ def find_files(pattern, path=None, root="rez"): author_email="rez-discussion@lists.aswf.io", license="Apache-2.0", license_files=["LICENSE"], - entry_points={ - "console_scripts": get_specifications().values() - }, + scripts=list(get_specifications().keys()), include_package_data=True, zip_safe=False, package_dir={'': 'src'}, @@ -99,5 +158,6 @@ def find_files(pattern, path=None, root="rez"): "Programming Language :: Python :: 3", "Topic :: Software Development", "Topic :: System :: Software Distribution" - ] + ], + cmdclass={"build_scripts": build_scripts}, ) diff --git a/src/rez/cli/_entry_points.py b/src/rez/cli/_entry_points.py index 8841932d9a..f37dee5794 100644 --- a/src/rez/cli/_entry_points.py +++ b/src/rez/cli/_entry_points.py @@ -34,15 +34,15 @@ def get_specifications(): for attr, obj in sys.modules[__name__].__dict__.items(): scriptname = getattr(obj, "__scriptname__", None) if scriptname: - spec = "%s = rez.cli._entry_points:%s" % (scriptname, attr) - specs[scriptname] = spec + specs[scriptname] = {"func": attr, "type": getattr(obj, "__scripttype__")} return specs -def scriptname(name): +def register(name, _type="console"): def decorator(fn): setattr(fn, "__scriptname__", name) + setattr(fn, "__scripttype__", _type) return fn return decorator @@ -62,14 +62,21 @@ def check_production_install(): ### Entry points -@scriptname("rez") +@register("jctest") +def run_jctest(): + print("argv:", sys.argv) + print("executable:", sys.executable) + return 0 + + +@register("rez") def run_rez(): check_production_install() from rez.cli._main import run return run() -@scriptname("rezolve") +@register("rezolve") def run_rezolve(): # alias for osx, where rez is a different tool # https://www.unix.com/man-page/osx/1/REZ/ @@ -78,196 +85,196 @@ def run_rezolve(): return run() -@scriptname("_rez-complete") +@register("_rez-complete") def run_rez_complete(): check_production_install() from rez.cli._main import run return run("complete") -@scriptname("_rez_fwd") +@register("_rez_fwd") def run_rez_fwd(): check_production_install() from rez.cli._main import run return run("forward") -@scriptname("rez-bind") +@register("rez-bind") def run_rez_bind(): check_production_install() from rez.cli._main import run return run("bind") -@scriptname("rez-build") +@register("rez-build") def run_rez_build(): check_production_install() from rez.cli._main import run return run("build") -@scriptname("rez-config") +@register("rez-config") def run_rez_config(): check_production_install() from rez.cli._main import run return run("config") -@scriptname("rez-context") +@register("rez-context") def run_rez_context(): check_production_install() from rez.cli._main import run return run("context") -@scriptname("rez-cp") +@register("rez-cp") def run_rez_cp(): check_production_install() from rez.cli._main import run return run("cp") -@scriptname("rez-depends") +@register("rez-depends") def run_rez_depends(): check_production_install() from rez.cli._main import run return run("depends") -@scriptname("rez-diff") +@register("rez-diff") def run_rez_diff(): check_production_install() from rez.cli._main import run return run("diff") -@scriptname("rez-env") +@register("rez-env") def run_rez_env(): check_production_install() from rez.cli._main import run return run("env") -@scriptname("rez-gui") +@register("rez-gui", "window") def run_rez_gui(): check_production_install() from rez.cli._main import run return run("gui") -@scriptname("rez-help") +@register("rez-help") def run_rez_help(): check_production_install() from rez.cli._main import run return run("help") -@scriptname("rez-interpret") +@register("rez-interpret") def run_rez_interpret(): check_production_install() from rez.cli._main import run return run("interpret") -@scriptname("rez-memcache") +@register("rez-memcache") def run_rez_memcache(): check_production_install() from rez.cli._main import run return run("memcache") -@scriptname("rez-pip") +@register("rez-pip") def run_rez_pip(): check_production_install() from rez.cli._main import run return run("pip") -@scriptname("rez-pkg-cache") +@register("rez-pkg-cache") def run_rez_pkg_cache(): check_production_install() from rez.cli._main import run return run("pkg-cache") -@scriptname("rez-plugins") +@register("rez-plugins") def run_rez_plugins(): check_production_install() from rez.cli._main import run return run("plugins") -@scriptname("rez-python") +@register("rez-python") def run_rez_python(): check_production_install() from rez.cli._main import run return run("python") -@scriptname("rez-release") +@register("rez-release") def run_rez_release(): check_production_install() from rez.cli._main import run return run("release") -@scriptname("rez-search") +@register("rez-search") def run_rez_search(): check_production_install() from rez.cli._main import run return run("search") -@scriptname("rez-selftest") +@register("rez-selftest") def run_rez_selftest(): check_production_install() from rez.cli._main import run return run("selftest") -@scriptname("rez-status") +@register("rez-status") def run_rez_status(): check_production_install() from rez.cli._main import run return run("status") -@scriptname("rez-suite") +@register("rez-suite") def run_rez_suite(): check_production_install() from rez.cli._main import run return run("suite") -@scriptname("rez-test") +@register("rez-test") def run_rez_test(): check_production_install() from rez.cli._main import run return run("test") -@scriptname("rez-view") +@register("rez-view") def run_rez_view(): check_production_install() from rez.cli._main import run return run("view") -@scriptname("rez-yaml2py") +@register("rez-yaml2py") def run_rez_yaml2py(): check_production_install() from rez.cli._main import run return run("yaml2py") -@scriptname("rez-bundle") +@register("rez-bundle") def run_rez_bundle(): check_production_install() from rez.cli._main import run return run("bundle") -@scriptname("rez-benchmark") +@register("rez-benchmark") def run_rez_benchmark(): check_production_install() @@ -295,21 +302,21 @@ def run_rez_benchmark(): return run("benchmark") -@scriptname("rez-pkg-ignore") +@register("rez-pkg-ignore") def run_rez_pkg_ignore(): check_production_install() from rez.cli._main import run return run("pkg-ignore") -@scriptname("rez-mv") +@register("rez-mv") def run_rez_mv(): check_production_install() from rez.cli._main import run return run("mv") -@scriptname("rez-rm") +@register("rez-rm") def run_rez_rm(): check_production_install() from rez.cli._main import run