forked from pypa/setuptools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
bootstrap.py
104 lines (83 loc) · 2.66 KB
/
bootstrap.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
"""
If setuptools is not already installed in the environment, it's not possible
to invoke setuptools' own commands. This routine will bootstrap this local
environment by creating a minimal egg-info directory and then invoking the
egg-info command to flesh out the egg-info directory.
"""
from __future__ import unicode_literals
import os
import io
import re
import contextlib
import tempfile
import shutil
import sys
import textwrap
import subprocess
minimal_egg_info = textwrap.dedent("""
[distutils.commands]
egg_info = setuptools.command.egg_info:egg_info
[distutils.setup_keywords]
include_package_data = setuptools.dist:assert_bool
install_requires = setuptools.dist:check_requirements
extras_require = setuptools.dist:check_extras
entry_points = setuptools.dist:check_entry_points
[egg_info.writers]
dependency_links.txt = setuptools.command.egg_info:overwrite_arg
entry_points.txt = setuptools.command.egg_info:write_entries
requires.txt = setuptools.command.egg_info:write_requirements
""")
def ensure_egg_info():
if os.path.exists('setuptools.egg-info'):
return
print("adding minimal entry_points")
build_egg_info()
def build_egg_info():
"""
Build a minimal egg-info, enough to invoke egg_info
"""
os.mkdir('setuptools.egg-info')
filename = 'setuptools.egg-info/entry_points.txt'
with io.open(filename, 'w', encoding='utf-8') as ep:
ep.write(minimal_egg_info)
def run_egg_info():
cmd = [sys.executable, 'setup.py', 'egg_info']
print("Regenerating egg_info")
subprocess.check_call(cmd)
print("...and again.")
subprocess.check_call(cmd)
def gen_deps():
with io.open('setup.py', encoding='utf-8') as strm:
text = strm.read()
pattern = r'install_requires=\[(.*?)\]'
match = re.search(pattern, text, flags=re.M|re.DOTALL)
reqs = eval(match.group(1).replace('\n', ''))
with io.open('requirements.txt', 'w', encoding='utf-8') as reqs_file:
reqs_file.write('\n'.join(reqs))
@contextlib.contextmanager
def install_deps():
"Just in time make the deps available"
import pip
tmpdir = tempfile.mkdtemp()
args = [
'install',
'-t', tmpdir,
'-r', 'requirements.txt',
]
pip.main(args)
os.environ['PYTHONPATH'] = tmpdir
try:
yield tmpdir
finally:
shutil.rmtree(tmpdir)
def main():
ensure_egg_info()
gen_deps()
try:
# first assume dependencies are present
run_egg_info()
except Exception:
# but if that fails, try again with dependencies just in time
with install_deps():
run_egg_info()
__name__ == '__main__' and main()