11#!/usr/bin/python
22
3- # Copyright (c) 2015 nexB Inc. http://www.nexb.com/ - All rights reserved.
3+ # Copyright (c) 2018 nexB Inc. http://www.nexb.com/ - All rights reserved.
44
55"""
6- This script a configuration helper to select pip requirement files to install
6+ This script is a configuration helper to select pip requirement files to install
77and python and shell configuration scripts to execute based on provided config
88directories paths arguments and the operating system platform. To use, create
99a configuration directory tree that contains any of these:
2121 - posix.sh, linux.sh, mac.sh are os-specific scripts to execute.
2222
2323The config directory structure contains one or more directories paths. This
24- way you can have a main configuration and additional sub-configurations of a
25- product such as for prod, test, ci, dev, or anything else.
24+ way you can have a main configuration (that is always used) and additional
25+ sub-configurations of a product such as for prod, test, ci, dev, or anything
26+ else.
2627
2728All scripts and requirements are optional and only used if presents. Scripts
2829are executed in sequence, one after the other after all requirements are
6768# platform-specific file base names
6869sys_platform = str (sys .platform ).lower ()
6970on_win = False
70- if 'linux' in sys_platform :
71+ if sys_platform . startswith ( 'linux' ) :
7172 platform_names = ('posix' , 'linux' ,)
72- elif 'win32' in sys_platform :
73+ elif 'win32' in sys_platform :
7374 platform_names = ('win' ,)
7475 on_win = True
7576elif 'darwin' in sys_platform :
7677 platform_names = ('posix' , 'mac' ,)
7778else :
78- raise Exception ('Unsupported OS/platform' )
79+ raise Exception ('Unsupported OS/platform %r' % sys_platform )
7980 platform_names = tuple ()
8081
8182
@@ -157,7 +158,7 @@ def build_pip_dirs_args(paths, root_dir, option='--extra-search-dir='):
157158 if not os .path .isabs (path ):
158159 path = os .path .join (root_dir , path )
159160 if os .path .exists (path ):
160- yield option + path
161+ yield option + '"' + path + '"'
161162
162163
163164def create_virtualenv (std_python , root_dir , tpp_dirs , quiet = False ):
@@ -176,13 +177,14 @@ def create_virtualenv(std_python, root_dir, tpp_dirs, quiet=False):
176177 vendored Python distributions that pip will use to find required
177178 components.
178179 """
179- print ("* Configuring Python ..." )
180+ if not quiet :
181+ print ("* Configuring Python ..." )
180182 # search virtualenv.py in the tpp_dirs. keep the first found
181183 venv_py = None
182184 for tpd in tpp_dirs :
183185 venv = os .path .join (root_dir , tpd , 'virtualenv.py' )
184186 if os .path .exists (venv ):
185- venv_py = venv
187+ venv_py = '"' + venv + '"'
186188 break
187189
188190 # error out if venv_py not found
@@ -196,12 +198,13 @@ def create_virtualenv(std_python, root_dir, tpp_dirs, quiet=False):
196198 # third parties may be in more than one directory
197199 vcmd .extend (build_pip_dirs_args (tpp_dirs , root_dir ))
198200 # we create the virtualenv in the root_dir
199- vcmd .append (root_dir )
201+ vcmd .append ('"' + root_dir + '"' )
200202 call (vcmd , root_dir )
201203
202204
203205def activate (root_dir ):
204206 """ Activate a virtualenv in the current process."""
207+ bin_dir = os .path .join (root_dir , 'bin' )
205208 activate_this = os .path .join (bin_dir , 'activate_this.py' )
206209 with open (activate_this ) as f :
207210 code = compile (f .read (), activate_this , 'exec' )
@@ -213,37 +216,45 @@ def install_3pp(configs, root_dir, tpp_dirs, quiet=False):
213216 Install requirements from requirement files found in `configs` with pip,
214217 using the vendored components in `tpp_dirs`.
215218 """
216- print ("* Installing components ..." )
217- requirement_files = get_conf_files (configs , root_dir , requirements )
219+ if not quiet :
220+ print ("* Installing components ..." )
221+ requirement_files = get_conf_files (configs , root_dir , requirements , quiet )
222+ if on_win :
223+ bin_dir = os .path .join (root_dir , 'bin' )
224+ configured_python = os .path .join (bin_dir , 'python.exe' )
225+ base_cmd = [configured_python , '-m' , 'pip' ]
226+ else :
227+ base_cmd = ['pip' ]
218228 for req_file in requirement_files :
219- pcmd = ['pip' , 'install' , '--no-allow-external' ,
220- '--use-wheel' , '--no-index' , '--no-cache-dir' ]
229+ pcmd = base_cmd + ['install' , '--upgrade' , '--no-index' , '--no-cache-dir' ]
221230 if quiet :
222231 pcmd += ['--quiet' ]
223232 pip_dir_args = list (build_pip_dirs_args (tpp_dirs , root_dir , '--find-links=' ))
224233 pcmd .extend (pip_dir_args )
225234 req_loc = os .path .join (root_dir , req_file )
226- pcmd .extend (['-r' , req_loc ])
235+ pcmd .extend (['-r' , '"' + req_loc + '"' ])
227236 call (pcmd , root_dir )
228237
229238
230- def run_scripts (configs , root_dir , configured_python ):
239+ def run_scripts (configs , root_dir , configured_python , quiet = False ):
231240 """
232241 Run Python scripts and shell scripts found in `configs`.
233242 """
234- print ("* Configuring ..." )
243+ if not quiet :
244+ print ("* Configuring ..." )
235245 # Run Python scripts for each configurations
236246 for py_script in get_conf_files (configs , root_dir , python_scripts ):
237- cmd = [configured_python , os .path .join (root_dir , py_script )]
247+ cmd = [configured_python , '"' + os .path .join (root_dir , py_script ) + '"' ]
238248 call (cmd , root_dir )
239249
240250 # Run sh_script scripts for each configurations
241251 for sh_script in get_conf_files (configs , root_dir , shell_scripts ):
242- # we source the scripts on posix
243- cmd = ['.' ]
244252 if on_win :
245253 cmd = []
246- cmd = cmd + [os .path .join (root_dir , sh_script )]
254+ else :
255+ # we source the scripts on posix
256+ cmd = ['.' ]
257+ cmd .extend ([os .path .join (root_dir , sh_script )])
247258 call (cmd , root_dir )
248259
249260
@@ -258,7 +269,7 @@ def chmod_bin(directory):
258269 os .chmod (os .path .join (path , f ), rwx )
259270
260271
261- def get_conf_files (config_dir_paths , root_dir , file_names = requirements ):
272+ def get_conf_files (config_dir_paths , root_dir , file_names = requirements , quiet = False ):
262273 """
263274 Return a list of collected path-prefixed file paths matching names in a
264275 file_names tuple, based on config_dir_paths, root_dir and the types of
@@ -286,8 +297,9 @@ def get_conf_files(config_dir_paths, root_dir, file_names=requirements):
286297 for config_dir_path in config_dir_paths :
287298 abs_config_dir_path = os .path .join (root_dir , config_dir_path )
288299 if not os .path .exists (abs_config_dir_path ):
289- print ('Configuration directory %(config_dir_path)s '
290- 'does not exists. Skipping.' % locals ())
300+ if not quiet :
301+ print ('Configuration directory %(config_dir_path)s '
302+ 'does not exists. Skipping.' % locals ())
291303 continue
292304 # Support args like enterprise or enterprise/dev
293305 paths = config_dir_path .strip ('/' ).replace ('\\ ' , '/' ).split ('/' )
@@ -313,31 +325,42 @@ def get_conf_files(config_dir_paths, root_dir, file_names=requirements):
313325 return collected
314326
315327
328+ usage = '\n Usage: configure [--clean] <path/to/configuration/directory> ...\n '
329+
330+
316331if __name__ == '__main__' :
332+
333+ # you must create a CONFIGURE_QUIET env var if you want to run quietly
334+ quiet = 'CONFIGURE_QUIET' in os .environ
335+
317336 # define/setup common directories
318337 etc_dir = os .path .abspath (os .path .dirname (__file__ ))
319338 root_dir = os .path .dirname (etc_dir )
320339
321340 args = sys .argv [1 :]
322- if args [0 ] == '--clean' :
323- clean (root_dir )
324- sys .exit (0 )
341+ if args :
342+ arg0 = args [0 ]
343+ if arg0 == '--clean' :
344+ clean (root_dir )
345+ sys .exit (0 )
346+ elif arg0 .startswith ('-' ):
347+ print ()
348+ print ('ERROR: unknown option: %(arg0)s' % locals ())
349+ print (usage )
350+ sys .exit (1 )
325351
326352 sys .path .insert (0 , root_dir )
327353 bin_dir = os .path .join (root_dir , 'bin' )
328354 standard_python = sys .executable
329355
330- # you must create a CONFIGURE_QUIET env var if you want to run quietly
331- run_quiet = 'CONFIGURE_QUIET' in os .environ
332-
333356 if on_win :
334357 configured_python = os .path .join (bin_dir , 'python.exe' )
335358 scripts_dir = os .path .join (root_dir , 'Scripts' )
336359 bin_dir = os .path .join (root_dir , 'bin' )
337360 if not os .path .exists (scripts_dir ):
338361 os .makedirs (scripts_dir )
339362 if not os .path .exists (bin_dir ):
340- cmd = ('mklink /J %(bin_dir)s %(scripts_dir)s' % locals ()).split ()
363+ cmd = ('mklink /J " %(bin_dir)s" " %(scripts_dir)s" ' % locals ()).split ()
341364 call (cmd , root_dir )
342365 else :
343366 configured_python = os .path .join (bin_dir , 'python' )
@@ -346,41 +369,47 @@ def get_conf_files(config_dir_paths, root_dir, file_names=requirements):
346369 # Get requested configuration paths to collect components and scripts later
347370 configs = []
348371 for path in args [:]:
372+ abs_path = path
349373 if not os .path .isabs (path ):
350374 abs_path = os .path .join (root_dir , path )
351- if os .path .exists (abs_path ):
352- configs .append (path )
353- else :
354- print ()
355- print ('WARNING: Skipping missing Configuration directory:\n '
356- ' %(path)s does not exist.' % locals ())
375+ if not os .path .exists (abs_path ):
357376 print ()
377+ print ('ERROR: Configuration directory does not exists:\n '
378+ ' %(path)s: %(abs_path)r'
379+ % locals ())
380+ print (usage )
381+ sys .exit (1 )
382+
383+ configs .append (path )
358384
359385 # Collect vendor directories from environment variables: one or more third-
360386 # party directories may exist as environment variables prefixed with TPP_DIR
361387 thirdparty_dirs = []
362388 for envvar , path in os .environ .items ():
363389 if not envvar .startswith ('TPP_DIR' ):
364390 continue
391+ abs_path = path
365392 if not os .path .isabs (path ):
366393 abs_path = os .path .join (root_dir , path )
367- if os .path .exists (abs_path ):
368- thirdparty_dirs .append (path )
394+ if not os .path .exists (abs_path ):
395+ if not quiet :
396+ print ()
397+ print ('WARNING: Third-party Python libraries directory does not exists:\n '
398+ ' %(path)r: %(abs_path)r\n '
399+ ' Provided by environment variable:\n '
400+ ' set %(envvar)s=%(path)r' % locals ())
401+ print ()
369402 else :
370- print ()
371- print ('WARNING: Skipping missing Python thirdparty directory:\n '
372- ' %(path)s does not exist.\n '
373- ' Provided by environment variable:\n '
374- ' set %(envvar)s=%(path)s' % locals ())
375- print ()
403+ thirdparty_dirs .append (path )
376404
377405 # Finally execute our three steps: venv, install and scripts
378406 if not os .path .exists (configured_python ):
379- create_virtualenv (standard_python , root_dir , thirdparty_dirs , quiet = run_quiet )
407+ create_virtualenv (standard_python , root_dir , thirdparty_dirs , quiet = quiet )
380408 activate (root_dir )
381409
382- install_3pp (configs , root_dir , thirdparty_dirs , quiet = run_quiet )
383- run_scripts (configs , root_dir , configured_python )
410+ install_3pp (configs , root_dir , thirdparty_dirs , quiet = quiet )
411+ run_scripts (configs , root_dir , configured_python , quiet = quiet )
384412 chmod_bin (bin_dir )
385- print ("* Configuration completed." )
386- print ()
413+ if not quiet :
414+ print ("* Configuration completed." )
415+ print ()
0 commit comments