Skip to content

Commit 937e570

Browse files
committed
Updated configure script
1 parent 5be7346 commit 937e570

File tree

1 file changed

+97
-52
lines changed

1 file changed

+97
-52
lines changed

etc/configure.py

Lines changed: 97 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
- python scripts execution
3434
- shell scripts execution
3535
36-
On posix, posix Python and shell scripts are executed before mac or linux
36+
On posix, posix Python and shell scripts are executed before mac or linux
3737
scripts.
3838
3939
The base scripts or packages are always installed first before platform-
@@ -78,6 +78,7 @@
7878
raise Exception('Unsupported OS/platform')
7979
platform_names = tuple()
8080

81+
8182
# common file basenames for requirements and scripts
8283
base = ('base',)
8384

@@ -96,29 +97,45 @@
9697
shell_scripts = ('win.bat',)
9798

9899

99-
def call(cmd):
100+
def call(cmd, root_dir):
100101
""" Run a `cmd` command (as a list of args) with all env vars."""
101102
cmd = ' '.join(cmd)
102-
if subprocess.Popen(cmd, shell=True, env=dict(os.environ)).wait() != 0:
103+
if subprocess.Popen(cmd, shell=True, env=dict(os.environ), cwd=root_dir).wait() != 0:
103104
print()
104-
print('Failed to execute command:\n%(cmd)s' % locals())
105+
print('Failed to execute command:\n%(cmd)s. Aborting...' % locals())
105106
sys.exit(1)
106107

107108

109+
def find_pycache(root_dir):
110+
"""
111+
Yield __pycache__ directory paths found in root_dir as paths relative to
112+
root_dir.
113+
"""
114+
for top, dirs, _files in os.walk(root_dir):
115+
for d in dirs:
116+
if d == '__pycache__':
117+
dir_path = os.path.join(top, d)
118+
dir_path = dir_path.replace(root_dir, '', 1)
119+
dir_path = dir_path.strip(os.path.sep)
120+
yield dir_path
121+
122+
108123
def clean(root_dir):
109124
"""
110-
Remove cleanable directories and files.
125+
Remove cleanable directories and files in root_dir.
111126
"""
112127
print('* Cleaning ...')
113-
cleanable = '''build bin lib include Scripts
128+
cleanable = '''build bin lib Lib include Include Scripts local
114129
django_background_task.log
115-
develop-eggs eggs parts .installed.cfg
130+
develop-eggs eggs parts .installed.cfg
116131
.Python
117132
.cache
118-
.settings
119133
pip-selfcheck.json
120134
'''.split()
121135

136+
# also clean __pycache__ if any
137+
cleanable.extend(find_pycache(root_dir))
138+
122139
for d in cleanable:
123140
try:
124141
loc = os.path.join(root_dir, d)
@@ -130,19 +147,23 @@ def clean(root_dir):
130147
except:
131148
pass
132149

133-
def build_pip_dirs_args(paths, option='--extra-search-dir='):
150+
151+
def build_pip_dirs_args(paths, root_dir, option='--extra-search-dir='):
134152
"""
135-
Return an iterable of pip command line arguments for the `option` pip
136-
command line option using a list of `paths` to directories.
153+
Return an iterable of pip command line options for `option` of pip using a
154+
list of `paths` to directories.
137155
"""
138156
for path in paths:
157+
if not os.path.isabs(path):
158+
path = os.path.join(root_dir, path)
139159
if os.path.exists(path):
140160
yield option + path
141161

142-
def create_virtualenv(std_python, root_dir, tpp_dirs):
162+
163+
def create_virtualenv(std_python, root_dir, tpp_dirs, quiet=False):
143164
"""
144165
Create a virtualenv in `root_dir` using the `std_python` Python
145-
executable. One of the tpp_dirs must contain a vendored virtualenv.py and
166+
executable. One of the `tpp_dirs` must contain a vendored virtualenv.py and
146167
virtualenv dependencies such as setuptools and pip packages.
147168
148169
@std_python: Path or name of the Python executable to use.
@@ -155,22 +176,28 @@ def create_virtualenv(std_python, root_dir, tpp_dirs):
155176
vendored Python distributions that pip will use to find required
156177
components.
157178
"""
158-
print()
159179
print("* Configuring Python ...")
160180
# search virtualenv.py in the tpp_dirs. keep the first found
161181
venv_py = None
162182
for tpd in tpp_dirs:
163-
venv = os.path.join(tpd, 'virtualenv.py')
183+
venv = os.path.join(root_dir, tpd, 'virtualenv.py')
164184
if os.path.exists(venv):
165185
venv_py = venv
166186
break
167-
# TODO: error out if venv_py not found
187+
188+
# error out if venv_py not found
189+
if not venv_py:
190+
print("Configuration Error ... aborting.")
191+
exit(1)
192+
168193
vcmd = [std_python, venv_py, '--never-download']
194+
if quiet:
195+
vcmd += ['--quiet']
169196
# third parties may be in more than one directory
170-
vcmd.extend(build_pip_dirs_args(tpp_dirs))
197+
vcmd.extend(build_pip_dirs_args(tpp_dirs, root_dir))
171198
# we create the virtualenv in the root_dir
172199
vcmd.append(root_dir)
173-
call(vcmd)
200+
call(vcmd, root_dir)
174201

175202

176203
def activate(root_dir):
@@ -181,36 +208,43 @@ def activate(root_dir):
181208
exec(code, dict(__file__=activate_this))
182209

183210

184-
def install_3pp(configs, root_dir, tpp_dirs):
185-
""" Install requirements with pip."""
186-
print()
211+
def install_3pp(configs, root_dir, tpp_dirs, quiet=False):
212+
"""
213+
Install requirements from requirement files found in `configs` with pip,
214+
using the vendored components in `tpp_dirs`.
215+
"""
187216
print("* Installing components ...")
188-
for req_file in get_conf_files(configs, requirements):
189-
pcmd = ['pip', 'install', '--no-allow-external',
217+
requirement_files = get_conf_files(configs, root_dir, requirements)
218+
for req_file in requirement_files:
219+
pcmd = ['pip', 'install', '--no-allow-external',
190220
'--use-wheel', '--no-index']
191-
pcmd.extend(build_pip_dirs_args(tpp_dirs, '--find-links='))
221+
if quiet:
222+
pcmd += ['--quiet']
223+
pip_dir_args = list(build_pip_dirs_args(tpp_dirs, root_dir, '--find-links='))
224+
pcmd.extend(pip_dir_args)
192225
req_loc = os.path.join(root_dir, req_file)
193226
pcmd.extend(['-r' , req_loc])
194-
call(pcmd)
227+
call(pcmd, root_dir)
195228

196229

197230
def run_scripts(configs, root_dir, configured_python):
198-
""" Run py_script and sh_script scripts."""
199-
print()
231+
"""
232+
Run Python scripts and shell scripts found in `configs`.
233+
"""
200234
print("* Configuring ...")
201235
# Run Python scripts for each configurations
202-
for py_script in get_conf_files(configs, python_scripts):
236+
for py_script in get_conf_files(configs, root_dir, python_scripts):
203237
cmd = [configured_python, os.path.join(root_dir, py_script)]
204-
call(cmd)
238+
call(cmd, root_dir)
205239

206240
# Run sh_script scripts for each configurations
207-
for sh_script in get_conf_files(configs, shell_scripts):
241+
for sh_script in get_conf_files(configs, root_dir, shell_scripts):
208242
# we source the scripts on posix
209243
cmd = ['.']
210244
if on_win:
211245
cmd = []
212-
cmd = cmd + [os.path.join(root_dir, sh_script)]
213-
call(cmd)
246+
cmd = cmd + [os.path.join(root_dir, sh_script)]
247+
call(cmd, root_dir)
214248

215249

216250
def chmod_bin(directory):
@@ -224,16 +258,18 @@ def chmod_bin(directory):
224258
os.chmod(os.path.join(path, f), rwx)
225259

226260

227-
def get_conf_files(config_dir_paths, file_names=requirements):
261+
def get_conf_files(config_dir_paths, root_dir, file_names=requirements):
228262
"""
229-
Based on config_dir_paths return a list of collected path-prefixed file
230-
paths matching names in a file_names tuple. Returned paths are posix
231-
paths.
263+
Return a list of collected path-prefixed file paths matching names in a
264+
file_names tuple, based on config_dir_paths, root_dir and the types of
265+
file_names requested. Returned paths are posix paths.
232266
233267
@config_dir_paths: Each config_dir_path is a relative from the project
234268
root to a config dir. This script should always be called from the project
235269
root dir.
236270
271+
@root_dir: The project absolute root dir.
272+
237273
@file_names: get requirements, python or shell files based on list of
238274
supported file names provided as a tuple of supported file_names.
239275
@@ -247,10 +283,10 @@ def get_conf_files(config_dir_paths, file_names=requirements):
247283
"""
248284
# collect files for each requested dir path
249285
collected = []
250-
251286
for config_dir_path in config_dir_paths:
252-
if not os.path.exists(config_dir_path):
253-
print('Configurtaion directory %(config_dir_path)s '
287+
abs_config_dir_path = os.path.join(root_dir, config_dir_path)
288+
if not os.path.exists(abs_config_dir_path):
289+
print('Configuration directory %(config_dir_path)s '
254290
'does not exists. Skipping.' % locals())
255291
continue
256292
# Support args like enterprise or enterprise/dev
@@ -259,19 +295,18 @@ def get_conf_files(config_dir_paths, file_names=requirements):
259295
current = None
260296
for path in paths:
261297
if not current:
262-
current = (path, os.path.abspath(path),)
298+
current = (path, os.path.join(root_dir, path),)
263299
else:
264300
base_path, base_loc = current
265301
current = (os.path.join(base_path, path),
266302
os.path.join(base_loc, path),)
267-
268303
path, loc = current
269304
# we iterate on known filenames to ensure the defined precedence
270305
# is respected (posix over mac, linux), etc
271306
for n in file_names:
272307
for f in os.listdir(loc):
273308
if f == n:
274-
f_loc = os.path.join(path, f)
309+
f_loc = os.path.join(loc, f)
275310
if f_loc not in collected:
276311
collected.append(f_loc)
277312

@@ -292,6 +327,9 @@ def get_conf_files(config_dir_paths, file_names=requirements):
292327
bin_dir = os.path.join(root_dir, 'bin')
293328
standard_python = sys.executable
294329

330+
# you must create a CONFIGURE_QUIET env var if you want to run quietly
331+
run_quiet = 'CONFIGURE_QUIET' in os.environ
332+
295333
if on_win:
296334
configured_python = os.path.join(bin_dir, 'python.exe')
297335
scripts_dir = os.path.join(root_dir, 'Scripts')
@@ -300,30 +338,34 @@ def get_conf_files(config_dir_paths, file_names=requirements):
300338
os.makedirs(scripts_dir)
301339
if not os.path.exists(bin_dir):
302340
cmd = ('mklink /J %(bin_dir)s %(scripts_dir)s' % locals()).split()
303-
call(cmd)
341+
call(cmd, root_dir)
304342
else:
305343
configured_python = os.path.join(bin_dir, 'python')
306344
scripts_dir = bin_dir
307345

308-
# get requested configuration paths and install components and run scripts
346+
# Get requested configuration paths to collect components and scripts later
309347
configs = []
310348
for path in args[:]:
311-
if os.path.exists(path):
312-
configs.append(path)
349+
if not os.path.isabs(path):
350+
abs_path = os.path.join(root_dir, path)
351+
if os.path.exists(abs_path):
352+
configs.append(path)
313353
else:
314354
print()
315355
print('WARNING: Skipping missing Configuration directory:\n'
316356
' %(path)s does not exist.' % locals())
317357
print()
318358

319-
# one or more third-party directories may exist
320-
# as environment variables prefixed with TPP_DIR
359+
# Collect vendor directories from environment variables: one or more third-
360+
# party directories may exist as environment variables prefixed with TPP_DIR
321361
thirdparty_dirs = []
322362
for envvar, path in os.environ.items():
323363
if not envvar.startswith('TPP_DIR'):
324364
continue
325-
if os.path.exists(path):
326-
thirdparty_dirs.append(path)
365+
if not os.path.isabs(path):
366+
abs_path = os.path.join(root_dir, path)
367+
if os.path.exists(abs_path):
368+
thirdparty_dirs.append(path)
327369
else:
328370
print()
329371
print('WARNING: Skipping missing Python thirdparty directory:\n'
@@ -332,10 +374,13 @@ def get_conf_files(config_dir_paths, file_names=requirements):
332374
' set %(envvar)s=%(path)s' % locals())
333375
print()
334376

377+
# Finally execute our three steps: venv, install and scripts
335378
if not os.path.exists(configured_python):
336-
create_virtualenv(standard_python, root_dir, thirdparty_dirs)
379+
create_virtualenv(standard_python, root_dir, thirdparty_dirs, quiet=run_quiet)
337380
activate(root_dir)
338381

339-
install_3pp(configs, root_dir, thirdparty_dirs,)
382+
install_3pp(configs, root_dir, thirdparty_dirs, quiet=run_quiet)
340383
run_scripts(configs, root_dir, configured_python)
341384
chmod_bin(bin_dir)
385+
print("* Configuration completed.")
386+
print()

0 commit comments

Comments
 (0)