-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathsetup.py
112 lines (90 loc) · 3.61 KB
/
setup.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
#!/usr/bin/env python3
import os
import sys
from pathlib import Path
import setuptools.command.install_lib
import subprocess
import os.path
from setuptools import setup, find_packages
from typing import List, Callable
version = (Path(__file__).parent / "orchestra/support/VERSION").read_text().strip()
ensure_ytt_path = Path(__file__).parent / "orchestra/support/ensure_ytt.py"
# For unknown reasons, setuptools does not preserve package_data file permissions so we need to set the executable
# flag ourselves
executable_support_files = [
"support/ytt",
"support/elf-replace-dynstr.py",
"support/verify-root.py",
"support/ensure_ytt.py",
]
def is_an_executable_support_file(path: str):
return any(path.endswith(f) for f in executable_support_files)
def is_python_script(path: str):
return path.lower().endswith(".py")
def set_executable_bit(install_lib_instance: setuptools.command.install_lib.install_lib):
for filename in install_lib_instance.get_outputs():
if is_an_executable_support_file(filename):
mode = (os.stat(filename).st_mode | 0o555) & 0o7777
print(f"Changing mode of {filename} to {mode:o}")
os.chmod(filename, mode)
def fix_shebang(install_lib_instance: setuptools.command.install_lib.install_lib):
for filename in install_lib_instance.get_outputs():
if is_an_executable_support_file(filename) and is_python_script(filename):
with open(filename) as f:
lines = f.readlines()
assert lines[0].startswith("#!")
lines[0] = f"#!{sys.executable}{os.linesep}"
with open(filename, "w") as f:
f.writelines(lines)
class ExtensibleInstallLibCommandFactory:
def __init__(
self,
additional_actions: List[Callable[[setuptools.command.install_lib.install_lib], None]],
):
"""Provides a way to create a class that extends setuptools install_lib commands and executes arbitrary actions
after it the default one has finished. Each additional action to be performed must be a Callable which takes an
install_lib instance as argument.
"""
self.additional_actions: List[Callable[[setuptools.command.install_lib.install_lib], None]] = additional_actions
def get_command(self):
additional_actions = self.additional_actions
class ExtensibleInstallLibCommand(setuptools.command.install_lib.install_lib):
def run(self):
setuptools.command.install_lib.install_lib.run(self)
for action in additional_actions:
action(self)
return ExtensibleInstallLibCommand
custom_install_lib_cmd = ExtensibleInstallLibCommandFactory(
additional_actions=[
fix_shebang,
set_executable_bit,
]
).get_command()
subprocess.check_call([ensure_ytt_path])
setup(
name="orchestra",
version=version,
description="The orchestra meta build system",
author="Filippo Cremonese (rev.ng SRLs)",
author_email="filippocremonese@rev.ng",
url="https://github.com/revng/revng-orchestra",
packages=find_packages(include=["orchestra*"]),
package_data={
"orchestra": [
"support/shell-home/.bashrc",
"support/shell-home/.zshrc",
"support/config.schema.yml",
"support/VERSION",
]
+ executable_support_files
},
install_requires=open("requirements.txt").readlines(),
entry_points={
"console_scripts": [
"orchestra=orchestra:main",
"orc=orchestra:main",
]
},
zip_safe=False,
cmdclass={"install_lib": custom_install_lib_cmd},
)