diff options
Diffstat (limited to 'dodai-devstrap.py')
-rw-r--r-- | dodai-devstrap.py | 1771 |
1 files changed, 1771 insertions, 0 deletions
diff --git a/dodai-devstrap.py b/dodai-devstrap.py new file mode 100644 index 0000000..48face5 --- /dev/null +++ b/dodai-devstrap.py | |||
@@ -0,0 +1,1771 @@ | |||
1 | #!/usr/bin/env python | ||
2 | ## WARNING: This file is generated | ||
3 | #!/usr/bin/env python | ||
4 | """Create a "virtual" Python installation | ||
5 | """ | ||
6 | |||
7 | virtualenv_version = "1.5.1" | ||
8 | |||
9 | import sys | ||
10 | import os | ||
11 | import optparse | ||
12 | import re | ||
13 | import shutil | ||
14 | import logging | ||
15 | import tempfile | ||
16 | import distutils.sysconfig | ||
17 | try: | ||
18 | import subprocess | ||
19 | except ImportError, e: | ||
20 | if sys.version_info <= (2, 3): | ||
21 | print 'ERROR: %s' % e | ||
22 | print 'ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.' | ||
23 | print 'If you copy subprocess.py from a newer version of Python this script will probably work' | ||
24 | sys.exit(101) | ||
25 | else: | ||
26 | raise | ||
27 | try: | ||
28 | set | ||
29 | except NameError: | ||
30 | from sets import Set as set | ||
31 | |||
32 | join = os.path.join | ||
33 | py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) | ||
34 | |||
35 | is_jython = sys.platform.startswith('java') | ||
36 | is_pypy = hasattr(sys, 'pypy_version_info') | ||
37 | |||
38 | if is_pypy: | ||
39 | expected_exe = 'pypy-c' | ||
40 | elif is_jython: | ||
41 | expected_exe = 'jython' | ||
42 | else: | ||
43 | expected_exe = 'python' | ||
44 | |||
45 | |||
46 | REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', | ||
47 | 'fnmatch', 'locale', 'encodings', 'codecs', | ||
48 | 'stat', 'UserDict', 'readline', 'copy_reg', 'types', | ||
49 | 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', | ||
50 | 'zlib'] | ||
51 | |||
52 | REQUIRED_FILES = ['lib-dynload', 'config'] | ||
53 | |||
54 | if sys.version_info[:2] >= (2, 6): | ||
55 | REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) | ||
56 | if sys.version_info[:2] >= (2, 7): | ||
57 | REQUIRED_MODULES.extend(['_weakrefset']) | ||
58 | if sys.version_info[:2] <= (2, 3): | ||
59 | REQUIRED_MODULES.extend(['sets', '__future__']) | ||
60 | if is_pypy: | ||
61 | # these are needed to correctly display the exceptions that may happen | ||
62 | # during the bootstrap | ||
63 | REQUIRED_MODULES.extend(['traceback', 'linecache']) | ||
64 | |||
65 | class Logger(object): | ||
66 | |||
67 | """ | ||
68 | Logging object for use in command-line script. Allows ranges of | ||
69 | levels, to avoid some redundancy of displayed information. | ||
70 | """ | ||
71 | |||
72 | DEBUG = logging.DEBUG | ||
73 | INFO = logging.INFO | ||
74 | NOTIFY = (logging.INFO+logging.WARN)/2 | ||
75 | WARN = WARNING = logging.WARN | ||
76 | ERROR = logging.ERROR | ||
77 | FATAL = logging.FATAL | ||
78 | |||
79 | LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] | ||
80 | |||
81 | def __init__(self, consumers): | ||
82 | self.consumers = consumers | ||
83 | self.indent = 0 | ||
84 | self.in_progress = None | ||
85 | self.in_progress_hanging = False | ||
86 | |||
87 | def debug(self, msg, *args, **kw): | ||
88 | self.log(self.DEBUG, msg, *args, **kw) | ||
89 | def info(self, msg, *args, **kw): | ||
90 | self.log(self.INFO, msg, *args, **kw) | ||
91 | def notify(self, msg, *args, **kw): | ||
92 | self.log(self.NOTIFY, msg, *args, **kw) | ||
93 | def warn(self, msg, *args, **kw): | ||
94 | self.log(self.WARN, msg, *args, **kw) | ||
95 | def error(self, msg, *args, **kw): | ||
96 | self.log(self.WARN, msg, *args, **kw) | ||
97 | def fatal(self, msg, *args, **kw): | ||
98 | self.log(self.FATAL, msg, *args, **kw) | ||
99 | def log(self, level, msg, *args, **kw): | ||
100 | if args: | ||
101 | if kw: | ||
102 | raise TypeError( | ||
103 | "You may give positional or keyword arguments, not both") | ||
104 | args = args or kw | ||
105 | rendered = None | ||
106 | for consumer_level, consumer in self.consumers: | ||
107 | if self.level_matches(level, consumer_level): | ||
108 | if (self.in_progress_hanging | ||
109 | and consumer in (sys.stdout, sys.stderr)): | ||
110 | self.in_progress_hanging = False | ||
111 | sys.stdout.write('\n') | ||
112 | sys.stdout.flush() | ||
113 | if rendered is None: | ||
114 | if args: | ||
115 | rendered = msg % args | ||
116 | else: | ||
117 | rendered = msg | ||
118 | rendered = ' '*self.indent + rendered | ||
119 | if hasattr(consumer, 'write'): | ||
120 | consumer.write(rendered+'\n') | ||
121 | else: | ||
122 | consumer(rendered) | ||
123 | |||
124 | def start_progress(self, msg): | ||
125 | assert not self.in_progress, ( | ||
126 | "Tried to start_progress(%r) while in_progress %r" | ||
127 | % (msg, self.in_progress)) | ||
128 | if self.level_matches(self.NOTIFY, self._stdout_level()): | ||
129 | sys.stdout.write(msg) | ||
130 | sys.stdout.flush() | ||
131 | self.in_progress_hanging = True | ||
132 | else: | ||
133 | self.in_progress_hanging = False | ||
134 | self.in_progress = msg | ||
135 | |||
136 | def end_progress(self, msg='done.'): | ||
137 | assert self.in_progress, ( | ||
138 | "Tried to end_progress without start_progress") | ||
139 | if self.stdout_level_matches(self.NOTIFY): | ||
140 | if not self.in_progress_hanging: | ||
141 | # Some message has been printed out since start_progress | ||
142 | sys.stdout.write('...' + self.in_progress + msg + '\n') | ||
143 | sys.stdout.flush() | ||
144 | else: | ||
145 | sys.stdout.write(msg + '\n') | ||
146 | sys.stdout.flush() | ||
147 | self.in_progress = None | ||
148 | self.in_progress_hanging = False | ||
149 | |||
150 | def show_progress(self): | ||
151 | """If we are in a progress scope, and no log messages have been | ||
152 | shown, write out another '.'""" | ||
153 | if self.in_progress_hanging: | ||
154 | sys.stdout.write('.') | ||
155 | sys.stdout.flush() | ||
156 | |||
157 | def stdout_level_matches(self, level): | ||
158 | """Returns true if a message at this level will go to stdout""" | ||
159 | return self.level_matches(level, self._stdout_level()) | ||
160 | |||
161 | def _stdout_level(self): | ||
162 | """Returns the level that stdout runs at""" | ||
163 | for level, consumer in self.consumers: | ||
164 | if consumer is sys.stdout: | ||
165 | return level | ||
166 | return self.FATAL | ||
167 | |||
168 | def level_matches(self, level, consumer_level): | ||
169 | """ | ||
170 | >>> l = Logger() | ||
171 | >>> l.level_matches(3, 4) | ||
172 | False | ||
173 | >>> l.level_matches(3, 2) | ||
174 | True | ||
175 | >>> l.level_matches(slice(None, 3), 3) | ||
176 | False | ||
177 | >>> l.level_matches(slice(None, 3), 2) | ||
178 | True | ||
179 | >>> l.level_matches(slice(1, 3), 1) | ||
180 | True | ||
181 | >>> l.level_matches(slice(2, 3), 1) | ||
182 | False | ||
183 | """ | ||
184 | if isinstance(level, slice): | ||
185 | start, stop = level.start, level.stop | ||
186 | if start is not None and start > consumer_level: | ||
187 | return False | ||
188 | if stop is not None or stop <= consumer_level: | ||
189 | return False | ||
190 | return True | ||
191 | else: | ||
192 | return level >= consumer_level | ||
193 | |||
194 | #@classmethod | ||
195 | def level_for_integer(cls, level): | ||
196 | levels = cls.LEVELS | ||
197 | if level < 0: | ||
198 | return levels[0] | ||
199 | if level >= len(levels): | ||
200 | return levels[-1] | ||
201 | return levels[level] | ||
202 | |||
203 | level_for_integer = classmethod(level_for_integer) | ||
204 | |||
205 | def mkdir(path): | ||
206 | if not os.path.exists(path): | ||
207 | logger.info('Creating %s', path) | ||
208 | os.makedirs(path) | ||
209 | else: | ||
210 | logger.info('Directory %s already exists', path) | ||
211 | |||
212 | def copyfile(src, dest, symlink=True): | ||
213 | if not os.path.exists(src): | ||
214 | # Some bad symlink in the src | ||
215 | logger.warn('Cannot find file %s (bad symlink)', src) | ||
216 | return | ||
217 | if os.path.exists(dest): | ||
218 | logger.debug('File %s already exists', dest) | ||
219 | return | ||
220 | if not os.path.exists(os.path.dirname(dest)): | ||
221 | logger.info('Creating parent directories for %s' % os.path.dirname(dest)) | ||
222 | os.makedirs(os.path.dirname(dest)) | ||
223 | if symlink and hasattr(os, 'symlink'): | ||
224 | logger.info('Symlinking %s', dest) | ||
225 | os.symlink(os.path.abspath(src), dest) | ||
226 | else: | ||
227 | logger.info('Copying to %s', dest) | ||
228 | if os.path.isdir(src): | ||
229 | shutil.copytree(src, dest, True) | ||
230 | else: | ||
231 | shutil.copy2(src, dest) | ||
232 | |||
233 | def writefile(dest, content, overwrite=True): | ||
234 | if not os.path.exists(dest): | ||
235 | logger.info('Writing %s', dest) | ||
236 | f = open(dest, 'wb') | ||
237 | f.write(content) | ||
238 | f.close() | ||
239 | return | ||
240 | else: | ||
241 | f = open(dest, 'rb') | ||
242 | c = f.read() | ||
243 | f.close() | ||
244 | if c != content: | ||
245 | if not overwrite: | ||
246 | logger.notify('File %s exists with different content; not overwriting', dest) | ||
247 | return | ||
248 | logger.notify('Overwriting %s with new content', dest) | ||
249 | f = open(dest, 'wb') | ||
250 | f.write(content) | ||
251 | f.close() | ||
252 | else: | ||
253 | logger.info('Content %s already in place', dest) | ||
254 | |||
255 | def rmtree(dir): | ||
256 | if os.path.exists(dir): | ||
257 | logger.notify('Deleting tree %s', dir) | ||
258 | shutil.rmtree(dir) | ||
259 | else: | ||
260 | logger.info('Do not need to delete %s; already gone', dir) | ||
261 | |||
262 | def make_exe(fn): | ||
263 | if hasattr(os, 'chmod'): | ||
264 | oldmode = os.stat(fn).st_mode & 07777 | ||
265 | newmode = (oldmode | 0555) & 07777 | ||
266 | os.chmod(fn, newmode) | ||
267 | logger.info('Changed mode of %s to %s', fn, oct(newmode)) | ||
268 | |||
269 | def _find_file(filename, dirs): | ||
270 | for dir in dirs: | ||
271 | if os.path.exists(join(dir, filename)): | ||
272 | return join(dir, filename) | ||
273 | return filename | ||
274 | |||
275 | def _install_req(py_executable, unzip=False, distribute=False): | ||
276 | if not distribute: | ||
277 | setup_fn = 'setuptools-0.6c11-py%s.egg' % sys.version[:3] | ||
278 | project_name = 'setuptools' | ||
279 | bootstrap_script = EZ_SETUP_PY | ||
280 | source = None | ||
281 | else: | ||
282 | setup_fn = None | ||
283 | source = 'distribute-0.6.14.tar.gz' | ||
284 | project_name = 'distribute' | ||
285 | bootstrap_script = DISTRIBUTE_SETUP_PY | ||
286 | try: | ||
287 | # check if the global Python has distribute installed or plain | ||
288 | # setuptools | ||
289 | import pkg_resources | ||
290 | if not hasattr(pkg_resources, '_distribute'): | ||
291 | location = os.path.dirname(pkg_resources.__file__) | ||
292 | logger.notify("A globally installed setuptools was found (in %s)" % location) | ||
293 | logger.notify("Use the --no-site-packages option to use distribute in " | ||
294 | "the virtualenv.") | ||
295 | except ImportError: | ||
296 | pass | ||
297 | |||
298 | search_dirs = file_search_dirs() | ||
299 | |||
300 | if setup_fn is not None: | ||
301 | setup_fn = _find_file(setup_fn, search_dirs) | ||
302 | |||
303 | if source is not None: | ||
304 | source = _find_file(source, search_dirs) | ||
305 | |||
306 | if is_jython and os._name == 'nt': | ||
307 | # Jython's .bat sys.executable can't handle a command line | ||
308 | # argument with newlines | ||
309 | fd, ez_setup = tempfile.mkstemp('.py') | ||
310 | os.write(fd, bootstrap_script) | ||
311 | os.close(fd) | ||
312 | cmd = [py_executable, ez_setup] | ||
313 | else: | ||
314 | cmd = [py_executable, '-c', bootstrap_script] | ||
315 | if unzip: | ||
316 | cmd.append('--always-unzip') | ||
317 | env = {} | ||
318 | remove_from_env = [] | ||
319 | if logger.stdout_level_matches(logger.DEBUG): | ||
320 | cmd.append('-v') | ||
321 | |||
322 | old_chdir = os.getcwd() | ||
323 | if setup_fn is not None and os.path.exists(setup_fn): | ||
324 | logger.info('Using existing %s egg: %s' % (project_name, setup_fn)) | ||
325 | cmd.append(setup_fn) | ||
326 | if os.environ.get('PYTHONPATH'): | ||
327 | env['PYTHONPATH'] = setup_fn + os.path.pathsep + os.environ['PYTHONPATH'] | ||
328 | else: | ||
329 | env['PYTHONPATH'] = setup_fn | ||
330 | else: | ||
331 | # the source is found, let's chdir | ||
332 | if source is not None and os.path.exists(source): | ||
333 | os.chdir(os.path.dirname(source)) | ||
334 | # in this case, we want to be sure that PYTHONPATH is unset (not | ||
335 | # just empty, really unset), else CPython tries to import the | ||
336 | # site.py that it's in virtualenv_support | ||
337 | remove_from_env.append('PYTHONPATH') | ||
338 | else: | ||
339 | logger.info('No %s egg found; downloading' % project_name) | ||
340 | cmd.extend(['--always-copy', '-U', project_name]) | ||
341 | logger.start_progress('Installing %s...' % project_name) | ||
342 | logger.indent += 2 | ||
343 | cwd = None | ||
344 | if project_name == 'distribute': | ||
345 | env['DONT_PATCH_SETUPTOOLS'] = 'true' | ||
346 | |||
347 | def _filter_ez_setup(line): | ||
348 | return filter_ez_setup(line, project_name) | ||
349 | |||
350 | if not os.access(os.getcwd(), os.W_OK): | ||
351 | cwd = tempfile.mkdtemp() | ||
352 | if source is not None and os.path.exists(source): | ||
353 | # the current working dir is hostile, let's copy the | ||
354 | # tarball to a temp dir | ||
355 | target = os.path.join(cwd, os.path.split(source)[-1]) | ||
356 | shutil.copy(source, target) | ||
357 | try: | ||
358 | call_subprocess(cmd, show_stdout=False, | ||
359 | filter_stdout=_filter_ez_setup, | ||
360 | extra_env=env, | ||
361 | remove_from_env=remove_from_env, | ||
362 | cwd=cwd) | ||
363 | finally: | ||
364 | logger.indent -= 2 | ||
365 | logger.end_progress() | ||
366 | if os.getcwd() != old_chdir: | ||
367 | os.chdir(old_chdir) | ||
368 | if is_jython and os._name == 'nt': | ||
369 | os.remove(ez_setup) | ||
370 | |||
371 | def file_search_dirs(): | ||
372 | here = os.path.dirname(os.path.abspath(__file__)) | ||
373 | dirs = ['.', here, | ||
374 | join(here, 'virtualenv_support')] | ||
375 | if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': | ||
376 | # Probably some boot script; just in case virtualenv is installed... | ||
377 | try: | ||
378 | import virtualenv | ||
379 | except ImportError: | ||
380 | pass | ||
381 | else: | ||
382 | dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virtualenv_support')) | ||
383 | return [d for d in dirs if os.path.isdir(d)] | ||
384 | |||
385 | def install_setuptools(py_executable, unzip=False): | ||
386 | _install_req(py_executable, unzip) | ||
387 | |||
388 | def install_distribute(py_executable, unzip=False): | ||
389 | _install_req(py_executable, unzip, distribute=True) | ||
390 | |||
391 | _pip_re = re.compile(r'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re.I) | ||
392 | def install_pip(py_executable): | ||
393 | filenames = [] | ||
394 | for dir in file_search_dirs(): | ||
395 | filenames.extend([join(dir, fn) for fn in os.listdir(dir) | ||
396 | if _pip_re.search(fn)]) | ||
397 | filenames = [(os.path.basename(filename).lower(), i, filename) for i, filename in enumerate(filenames)] | ||
398 | filenames.sort() | ||
399 | filenames = [filename for basename, i, filename in filenames] | ||
400 | if not filenames: | ||
401 | filename = 'pip' | ||
402 | else: | ||
403 | filename = filenames[-1] | ||
404 | easy_install_script = 'easy_install' | ||
405 | if sys.platform == 'win32': | ||
406 | easy_install_script = 'easy_install-script.py' | ||
407 | cmd = [py_executable, join(os.path.dirname(py_executable), easy_install_script), filename] | ||
408 | if filename == 'pip': | ||
409 | logger.info('Installing pip from network...') | ||
410 | else: | ||
411 | logger.info('Installing %s' % os.path.basename(filename)) | ||
412 | logger.indent += 2 | ||
413 | def _filter_setup(line): | ||
414 | return filter_ez_setup(line, 'pip') | ||
415 | try: | ||
416 | call_subprocess(cmd, show_stdout=False, | ||
417 | filter_stdout=_filter_setup) | ||
418 | finally: | ||
419 | logger.indent -= 2 | ||
420 | |||
421 | def filter_ez_setup(line, project_name='setuptools'): | ||
422 | if not line.strip(): | ||
423 | return Logger.DEBUG | ||
424 | if project_name == 'distribute': | ||
425 | for prefix in ('Extracting', 'Now working', 'Installing', 'Before', | ||
426 | 'Scanning', 'Setuptools', 'Egg', 'Already', | ||
427 | 'running', 'writing', 'reading', 'installing', | ||
428 | 'creating', 'copying', 'byte-compiling', 'removing', | ||
429 | 'Processing'): | ||
430 | if line.startswith(prefix): | ||
431 | return Logger.DEBUG | ||
432 | return Logger.DEBUG | ||
433 | for prefix in ['Reading ', 'Best match', 'Processing setuptools', | ||
434 | 'Copying setuptools', 'Adding setuptools', | ||
435 | 'Installing ', 'Installed ']: | ||
436 | if line.startswith(prefix): | ||
437 | return Logger.DEBUG | ||
438 | return Logger.INFO | ||
439 | |||
440 | def main(): | ||
441 | parser = optparse.OptionParser( | ||
442 | version=virtualenv_version, | ||
443 | usage="%prog [OPTIONS] DEST_DIR") | ||
444 | |||
445 | parser.add_option( | ||
446 | '-v', '--verbose', | ||
447 | action='count', | ||
448 | dest='verbose', | ||
449 | default=0, | ||
450 | help="Increase verbosity") | ||
451 | |||
452 | parser.add_option( | ||
453 | '-q', '--quiet', | ||
454 | action='count', | ||
455 | dest='quiet', | ||
456 | default=0, | ||
457 | help='Decrease verbosity') | ||
458 | |||
459 | parser.add_option( | ||
460 | '-p', '--python', | ||
461 | dest='python', | ||
462 | metavar='PYTHON_EXE', | ||
463 | help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' | ||
464 | 'interpreter to create the new environment. The default is the interpreter that ' | ||
465 | 'virtualenv was installed with (%s)' % sys.executable) | ||
466 | |||
467 | parser.add_option( | ||
468 | '--clear', | ||
469 | dest='clear', | ||
470 | action='store_true', | ||
471 | help="Clear out the non-root install and start from scratch") | ||
472 | |||
473 | parser.add_option( | ||
474 | '--no-site-packages', | ||
475 | dest='no_site_packages', | ||
476 | action='store_true', | ||
477 | help="Don't give access to the global site-packages dir to the " | ||
478 | "virtual environment") | ||
479 | |||
480 | parser.add_option( | ||
481 | '--unzip-setuptools', | ||
482 | dest='unzip_setuptools', | ||
483 | action='store_true', | ||
484 | help="Unzip Setuptools or Distribute when installing it") | ||
485 | |||
486 | parser.add_option( | ||
487 | '--relocatable', | ||
488 | dest='relocatable', | ||
489 | action='store_true', | ||
490 | help='Make an EXISTING virtualenv environment relocatable. ' | ||
491 | 'This fixes up scripts and makes all .pth files relative') | ||
492 | |||
493 | parser.add_option( | ||
494 | '--distribute', | ||
495 | dest='use_distribute', | ||
496 | action='store_true', | ||
497 | help='Use Distribute instead of Setuptools. Set environ variable ' | ||
498 | 'VIRTUALENV_USE_DISTRIBUTE to make it the default ') | ||
499 | |||
500 | parser.add_option( | ||
501 | '--prompt=', | ||
502 | dest='prompt', | ||
503 | help='Provides an alternative prompt prefix for this environment') | ||
504 | |||
505 | if 'extend_parser' in globals(): | ||
506 | extend_parser(parser) | ||
507 | |||
508 | options, args = parser.parse_args() | ||
509 | |||
510 | global logger | ||
511 | |||
512 | if 'adjust_options' in globals(): | ||
513 | adjust_options(options, args) | ||
514 | |||
515 | verbosity = options.verbose - options.quiet | ||
516 | logger = Logger([(Logger.level_for_integer(2-verbosity), sys.stdout)]) | ||
517 | |||
518 | if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): | ||
519 | env = os.environ.copy() | ||
520 | interpreter = resolve_interpreter(options.python) | ||
521 | if interpreter == sys.executable: | ||
522 | logger.warn('Already using interpreter %s' % interpreter) | ||
523 | else: | ||
524 | logger.notify('Running virtualenv with interpreter %s' % interpreter) | ||
525 | env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' | ||
526 | file = __file__ | ||
527 | if file.endswith('.pyc'): | ||
528 | file = file[:-1] | ||
529 | popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) | ||
530 | raise SystemExit(popen.wait()) | ||
531 | |||
532 | if not args: | ||
533 | print 'You must provide a DEST_DIR' | ||
534 | parser.print_help() | ||
535 | sys.exit(2) | ||
536 | if len(args) > 1: | ||
537 | print 'There must be only one argument: DEST_DIR (you gave %s)' % ( | ||
538 | ' '.join(args)) | ||
539 | parser.print_help() | ||
540 | sys.exit(2) | ||
541 | |||
542 | home_dir = args[0] | ||
543 | |||
544 | if os.environ.get('WORKING_ENV'): | ||
545 | logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') | ||
546 | logger.fatal('Please deactivate your workingenv, then re-run this script') | ||
547 | sys.exit(3) | ||
548 | |||
549 | if 'PYTHONHOME' in os.environ: | ||
550 | logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') | ||
551 | del os.environ['PYTHONHOME'] | ||
552 | |||
553 | if options.relocatable: | ||
554 | make_environment_relocatable(home_dir) | ||
555 | return | ||
556 | |||
557 | create_environment(home_dir, site_packages=not options.no_site_packages, clear=options.clear, | ||
558 | unzip_setuptools=options.unzip_setuptools, | ||
559 | use_distribute=options.use_distribute, | ||
560 | prompt=options.prompt) | ||
561 | if 'after_install' in globals(): | ||
562 | after_install(options, home_dir) | ||
563 | |||
564 | def call_subprocess(cmd, show_stdout=True, | ||
565 | filter_stdout=None, cwd=None, | ||
566 | raise_on_returncode=True, extra_env=None, | ||
567 | remove_from_env=None): | ||
568 | cmd_parts = [] | ||
569 | for part in cmd: | ||
570 | if len(part) > 40: | ||
571 | part = part[:30]+"..."+part[-5:] | ||
572 | if ' ' in part or '\n' in part or '"' in part or "'" in part: | ||
573 | part = '"%s"' % part.replace('"', '\\"') | ||
574 | cmd_parts.append(part) | ||
575 | cmd_desc = ' '.join(cmd_parts) | ||
576 | if show_stdout: | ||
577 | stdout = None | ||
578 | else: | ||
579 | stdout = subprocess.PIPE | ||
580 | logger.debug("Running command %s" % cmd_desc) | ||
581 | if extra_env or remove_from_env: | ||
582 | env = os.environ.copy() | ||
583 | if extra_env: | ||
584 | env.update(extra_env) | ||
585 | if remove_from_env: | ||
586 | for varname in remove_from_env: | ||
587 | env.pop(varname, None) | ||
588 | else: | ||
589 | env = None | ||
590 | try: | ||
591 | proc = subprocess.Popen( | ||
592 | cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout, | ||
593 | cwd=cwd, env=env) | ||
594 | except Exception, e: | ||
595 | logger.fatal( | ||
596 | "Error %s while executing command %s" % (e, cmd_desc)) | ||
597 | raise | ||
598 | all_output = [] | ||
599 | if stdout is not None: | ||
600 | stdout = proc.stdout | ||
601 | while 1: | ||
602 | line = stdout.readline() | ||
603 | if not line: | ||
604 | break | ||
605 | line = line.rstrip() | ||
606 | all_output.append(line) | ||
607 | if filter_stdout: | ||
608 | level = filter_stdout(line) | ||
609 | if isinstance(level, tuple): | ||
610 | level, line = level | ||
611 | logger.log(level, line) | ||
612 | if not logger.stdout_level_matches(level): | ||
613 | logger.show_progress() | ||
614 | else: | ||
615 | logger.info(line) | ||
616 | else: | ||
617 | proc.communicate() | ||
618 | proc.wait() | ||
619 | if proc.returncode: | ||
620 | if raise_on_returncode: | ||
621 | if all_output: | ||
622 | logger.notify('Complete output from command %s:' % cmd_desc) | ||
623 | logger.notify('\n'.join(all_output) + '\n----------------------------------------') | ||
624 | raise OSError( | ||
625 | "Command %s failed with error code %s" | ||
626 | % (cmd_desc, proc.returncode)) | ||
627 | else: | ||
628 | logger.warn( | ||
629 | "Command %s had error code %s" | ||
630 | % (cmd_desc, proc.returncode)) | ||
631 | |||
632 | |||
633 | def create_environment(home_dir, site_packages=True, clear=False, | ||
634 | unzip_setuptools=False, use_distribute=False, | ||
635 | prompt=None): | ||
636 | """ | ||
637 | Creates a new environment in ``home_dir``. | ||
638 | |||
639 | If ``site_packages`` is true (the default) then the global | ||
640 | ``site-packages/`` directory will be on the path. | ||
641 | |||
642 | If ``clear`` is true (default False) then the environment will | ||
643 | first be cleared. | ||
644 | """ | ||
645 | home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | ||
646 | |||
647 | py_executable = os.path.abspath(install_python( | ||
648 | home_dir, lib_dir, inc_dir, bin_dir, | ||
649 | site_packages=site_packages, clear=clear)) | ||
650 | |||
651 | install_distutils(home_dir) | ||
652 | |||
653 | if use_distribute or os.environ.get('VIRTUALENV_USE_DISTRIBUTE'): | ||
654 | install_distribute(py_executable, unzip=unzip_setuptools) | ||
655 | else: | ||
656 | install_setuptools(py_executable, unzip=unzip_setuptools) | ||
657 | |||
658 | install_pip(py_executable) | ||
659 | |||
660 | install_activate(home_dir, bin_dir, prompt) | ||
661 | |||
662 | def path_locations(home_dir): | ||
663 | """Return the path locations for the environment (where libraries are, | ||
664 | where scripts go, etc)""" | ||
665 | # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its | ||
666 | # prefix arg is broken: http://bugs.python.org/issue3386 | ||
667 | if sys.platform == 'win32': | ||
668 | # Windows has lots of problems with executables with spaces in | ||
669 | # the name; this function will remove them (using the ~1 | ||
670 | # format): | ||
671 | mkdir(home_dir) | ||
672 | if ' ' in home_dir: | ||
673 | try: | ||
674 | import win32api | ||
675 | except ImportError: | ||
676 | print 'Error: the path "%s" has a space in it' % home_dir | ||
677 | print 'To handle these kinds of paths, the win32api module must be installed:' | ||
678 | print ' http://sourceforge.net/projects/pywin32/' | ||
679 | sys.exit(3) | ||
680 | home_dir = win32api.GetShortPathName(home_dir) | ||
681 | lib_dir = join(home_dir, 'Lib') | ||
682 | inc_dir = join(home_dir, 'Include') | ||
683 | bin_dir = join(home_dir, 'Scripts') | ||
684 | elif is_jython: | ||
685 | lib_dir = join(home_dir, 'Lib') | ||
686 | inc_dir = join(home_dir, 'Include') | ||
687 | bin_dir = join(home_dir, 'bin') | ||
688 | elif is_pypy: | ||
689 | lib_dir = home_dir | ||
690 | inc_dir = join(home_dir, 'include') | ||
691 | bin_dir = join(home_dir, 'bin') | ||
692 | else: | ||
693 | lib_dir = join(home_dir, 'lib', py_version) | ||
694 | inc_dir = join(home_dir, 'include', py_version) | ||
695 | bin_dir = join(home_dir, 'bin') | ||
696 | return home_dir, lib_dir, inc_dir, bin_dir | ||
697 | |||
698 | |||
699 | def change_prefix(filename, dst_prefix): | ||
700 | prefixes = [sys.prefix] | ||
701 | if hasattr(sys, 'real_prefix'): | ||
702 | prefixes.append(sys.real_prefix) | ||
703 | prefixes = map(os.path.abspath, prefixes) | ||
704 | filename = os.path.abspath(filename) | ||
705 | for src_prefix in prefixes: | ||
706 | if filename.startswith(src_prefix): | ||
707 | _, relpath = filename.split(src_prefix, 1) | ||
708 | assert relpath[0] == os.sep | ||
709 | relpath = relpath[1:] | ||
710 | return join(dst_prefix, relpath) | ||
711 | assert False, "Filename %s does not start with any of these prefixes: %s" % \ | ||
712 | (filename, prefixes) | ||
713 | |||
714 | def copy_required_modules(dst_prefix): | ||
715 | import imp | ||
716 | for modname in REQUIRED_MODULES: | ||
717 | if modname in sys.builtin_module_names: | ||
718 | logger.info("Ignoring built-in bootstrap module: %s" % modname) | ||
719 | continue | ||
720 | try: | ||
721 | f, filename, _ = imp.find_module(modname) | ||
722 | except ImportError: | ||
723 | logger.info("Cannot import bootstrap module: %s" % modname) | ||
724 | else: | ||
725 | if f is not None: | ||
726 | f.close() | ||
727 | dst_filename = change_prefix(filename, dst_prefix) | ||
728 | copyfile(filename, dst_filename) | ||
729 | if filename.endswith('.pyc'): | ||
730 | pyfile = filename[:-1] | ||
731 | if os.path.exists(pyfile): | ||
732 | copyfile(pyfile, dst_filename[:-1]) | ||
733 | |||
734 | |||
735 | def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear): | ||
736 | """Install just the base environment, no distutils patches etc""" | ||
737 | if sys.executable.startswith(bin_dir): | ||
738 | print 'Please use the *system* python to run this script' | ||
739 | return | ||
740 | |||
741 | if clear: | ||
742 | rmtree(lib_dir) | ||
743 | ## FIXME: why not delete it? | ||
744 | ## Maybe it should delete everything with #!/path/to/venv/python in it | ||
745 | logger.notify('Not deleting %s', bin_dir) | ||
746 | |||
747 | if hasattr(sys, 'real_prefix'): | ||
748 | logger.notify('Using real prefix %r' % sys.real_prefix) | ||
749 | prefix = sys.real_prefix | ||
750 | else: | ||
751 | prefix = sys.prefix | ||
752 | mkdir(lib_dir) | ||
753 | fix_lib64(lib_dir) | ||
754 | stdlib_dirs = [os.path.dirname(os.__file__)] | ||
755 | if sys.platform == 'win32': | ||
756 | stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) | ||
757 | elif sys.platform == 'darwin': | ||
758 | stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) | ||
759 | if hasattr(os, 'symlink'): | ||
760 | logger.info('Symlinking Python bootstrap modules') | ||
761 | else: | ||
762 | logger.info('Copying Python bootstrap modules') | ||
763 | logger.indent += 2 | ||
764 | try: | ||
765 | # copy required files... | ||
766 | for stdlib_dir in stdlib_dirs: | ||
767 | if not os.path.isdir(stdlib_dir): | ||
768 | continue | ||
769 | for fn in os.listdir(stdlib_dir): | ||
770 | if fn != 'site-packages' and os.path.splitext(fn)[0] in REQUIRED_FILES: | ||
771 | copyfile(join(stdlib_dir, fn), join(lib_dir, fn)) | ||
772 | # ...and modules | ||
773 | copy_required_modules(home_dir) | ||
774 | finally: | ||
775 | logger.indent -= 2 | ||
776 | mkdir(join(lib_dir, 'site-packages')) | ||
777 | import site | ||
778 | site_filename = site.__file__ | ||
779 | if site_filename.endswith('.pyc'): | ||
780 | site_filename = site_filename[:-1] | ||
781 | elif site_filename.endswith('$py.class'): | ||
782 | site_filename = site_filename.replace('$py.class', '.py') | ||
783 | site_filename_dst = change_prefix(site_filename, home_dir) | ||
784 | site_dir = os.path.dirname(site_filename_dst) | ||
785 | writefile(site_filename_dst, SITE_PY) | ||
786 | writefile(join(site_dir, 'orig-prefix.txt'), prefix) | ||
787 | site_packages_filename = join(site_dir, 'no-global-site-packages.txt') | ||
788 | if not site_packages: | ||
789 | writefile(site_packages_filename, '') | ||
790 | else: | ||
791 | if os.path.exists(site_packages_filename): | ||
792 | logger.info('Deleting %s' % site_packages_filename) | ||
793 | os.unlink(site_packages_filename) | ||
794 | |||
795 | if is_pypy: | ||
796 | stdinc_dir = join(prefix, 'include') | ||
797 | else: | ||
798 | stdinc_dir = join(prefix, 'include', py_version) | ||
799 | if os.path.exists(stdinc_dir): | ||
800 | copyfile(stdinc_dir, inc_dir) | ||
801 | else: | ||
802 | logger.debug('No include dir %s' % stdinc_dir) | ||
803 | |||
804 | if sys.exec_prefix != prefix: | ||
805 | if sys.platform == 'win32': | ||
806 | exec_dir = join(sys.exec_prefix, 'lib') | ||
807 | elif is_jython: | ||
808 | exec_dir = join(sys.exec_prefix, 'Lib') | ||
809 | else: | ||
810 | exec_dir = join(sys.exec_prefix, 'lib', py_version) | ||
811 | for fn in os.listdir(exec_dir): | ||
812 | copyfile(join(exec_dir, fn), join(lib_dir, fn)) | ||
813 | |||
814 | if is_jython: | ||
815 | # Jython has either jython-dev.jar and javalib/ dir, or just | ||
816 | # jython.jar | ||
817 | for name in 'jython-dev.jar', 'javalib', 'jython.jar': | ||
818 | src = join(prefix, name) | ||
819 | if os.path.exists(src): | ||
820 | copyfile(src, join(home_dir, name)) | ||
821 | # XXX: registry should always exist after Jython 2.5rc1 | ||
822 | src = join(prefix, 'registry') | ||
823 | if os.path.exists(src): | ||
824 | copyfile(src, join(home_dir, 'registry'), symlink=False) | ||
825 | copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), | ||
826 | symlink=False) | ||
827 | |||
828 | mkdir(bin_dir) | ||
829 | py_executable = join(bin_dir, os.path.basename(sys.executable)) | ||
830 | if 'Python.framework' in prefix: | ||
831 | if re.search(r'/Python(?:-32|-64)*$', py_executable): | ||
832 | # The name of the python executable is not quite what | ||
833 | # we want, rename it. | ||
834 | py_executable = os.path.join( | ||
835 | os.path.dirname(py_executable), 'python') | ||
836 | |||
837 | logger.notify('New %s executable in %s', expected_exe, py_executable) | ||
838 | if sys.executable != py_executable: | ||
839 | ## FIXME: could I just hard link? | ||
840 | executable = sys.executable | ||
841 | if sys.platform == 'cygwin' and os.path.exists(executable + '.exe'): | ||
842 | # Cygwin misreports sys.executable sometimes | ||
843 | executable += '.exe' | ||
844 | py_executable += '.exe' | ||
845 | logger.info('Executable actually exists in %s' % executable) | ||
846 | shutil.copyfile(executable, py_executable) | ||
847 | make_exe(py_executable) | ||
848 | if sys.platform == 'win32' or sys.platform == 'cygwin': | ||
849 | pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') | ||
850 | if os.path.exists(pythonw): | ||
851 | logger.info('Also created pythonw.exe') | ||
852 | shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) | ||
853 | if is_pypy: | ||
854 | # make a symlink python --> pypy-c | ||
855 | python_executable = os.path.join(os.path.dirname(py_executable), 'python') | ||
856 | logger.info('Also created executable %s' % python_executable) | ||
857 | copyfile(py_executable, python_executable) | ||
858 | |||
859 | if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: | ||
860 | secondary_exe = os.path.join(os.path.dirname(py_executable), | ||
861 | expected_exe) | ||
862 | py_executable_ext = os.path.splitext(py_executable)[1] | ||
863 | if py_executable_ext == '.exe': | ||
864 | # python2.4 gives an extension of '.4' :P | ||
865 | secondary_exe += py_executable_ext | ||
866 | if os.path.exists(secondary_exe): | ||
867 | logger.warn('Not overwriting existing %s script %s (you must use %s)' | ||
868 | % (expected_exe, secondary_exe, py_executable)) | ||
869 | else: | ||
870 | logger.notify('Also creating executable in %s' % secondary_exe) | ||
871 | shutil.copyfile(sys.executable, secondary_exe) | ||
872 | make_exe(secondary_exe) | ||
873 | |||
874 | if 'Python.framework' in prefix: | ||
875 | logger.debug('MacOSX Python framework detected') | ||
876 | |||
877 | # Make sure we use the the embedded interpreter inside | ||
878 | # the framework, even if sys.executable points to | ||
879 | # the stub executable in ${sys.prefix}/bin | ||
880 | # See http://groups.google.com/group/python-virtualenv/ | ||
881 | # browse_thread/thread/17cab2f85da75951 | ||
882 | original_python = os.path.join( | ||
883 | prefix, 'Resources/Python.app/Contents/MacOS/Python') | ||
884 | shutil.copy(original_python, py_executable) | ||
885 | |||
886 | # Copy the framework's dylib into the virtual | ||
887 | # environment | ||
888 | virtual_lib = os.path.join(home_dir, '.Python') | ||
889 | |||
890 | if os.path.exists(virtual_lib): | ||
891 | os.unlink(virtual_lib) | ||
892 | copyfile( | ||
893 | os.path.join(prefix, 'Python'), | ||
894 | virtual_lib) | ||
895 | |||
896 | # And then change the install_name of the copied python executable | ||
897 | try: | ||
898 | call_subprocess( | ||
899 | ["install_name_tool", "-change", | ||
900 | os.path.join(prefix, 'Python'), | ||
901 | '@executable_path/../.Python', | ||
902 | py_executable]) | ||
903 | except: | ||
904 | logger.fatal( | ||
905 | "Could not call install_name_tool -- you must have Apple's development tools installed") | ||
906 | raise | ||
907 | |||
908 | # Some tools depend on pythonX.Y being present | ||
909 | py_executable_version = '%s.%s' % ( | ||
910 | sys.version_info[0], sys.version_info[1]) | ||
911 | if not py_executable.endswith(py_executable_version): | ||
912 | # symlinking pythonX.Y > python | ||
913 | pth = py_executable + '%s.%s' % ( | ||
914 | sys.version_info[0], sys.version_info[1]) | ||
915 | if os.path.exists(pth): | ||
916 | os.unlink(pth) | ||
917 | os.symlink('python', pth) | ||
918 | else: | ||
919 | # reverse symlinking python -> pythonX.Y (with --python) | ||
920 | pth = join(bin_dir, 'python') | ||
921 | if os.path.exists(pth): | ||
922 | os.unlink(pth) | ||
923 | os.symlink(os.path.basename(py_executable), pth) | ||
924 | |||
925 | if sys.platform == 'win32' and ' ' in py_executable: | ||
926 | # There's a bug with subprocess on Windows when using a first | ||
927 | # argument that has a space in it. Instead we have to quote | ||
928 | # the value: | ||
929 | py_executable = '"%s"' % py_executable | ||
930 | cmd = [py_executable, '-c', 'import sys; print sys.prefix'] | ||
931 | logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) | ||
932 | proc = subprocess.Popen(cmd, | ||
933 | stdout=subprocess.PIPE) | ||
934 | proc_stdout, proc_stderr = proc.communicate() | ||
935 | proc_stdout = os.path.normcase(os.path.abspath(proc_stdout.strip())) | ||
936 | if proc_stdout != os.path.normcase(os.path.abspath(home_dir)): | ||
937 | logger.fatal( | ||
938 | 'ERROR: The executable %s is not functioning' % py_executable) | ||
939 | logger.fatal( | ||
940 | 'ERROR: It thinks sys.prefix is %r (should be %r)' | ||
941 | % (proc_stdout, os.path.normcase(os.path.abspath(home_dir)))) | ||
942 | logger.fatal( | ||
943 | 'ERROR: virtualenv is not compatible with this system or executable') | ||
944 | if sys.platform == 'win32': | ||
945 | logger.fatal( | ||
946 | 'Note: some Windows users have reported this error when they installed Python for "Only this user". The problem may be resolvable if you install Python "For all users". (See https://bugs.launchpad.net/virtualenv/+bug/352844)') | ||
947 | sys.exit(100) | ||
948 | else: | ||
949 | logger.info('Got sys.prefix result: %r' % proc_stdout) | ||
950 | |||
951 | pydistutils = os.path.expanduser('~/.pydistutils.cfg') | ||
952 | if os.path.exists(pydistutils): | ||
953 | logger.notify('Please make sure you remove any previous custom paths from ' | ||
954 | 'your %s file.' % pydistutils) | ||
955 | ## FIXME: really this should be calculated earlier | ||
956 | return py_executable | ||
957 | |||
958 | def install_activate(home_dir, bin_dir, prompt=None): | ||
959 | if sys.platform == 'win32' or is_jython and os._name == 'nt': | ||
960 | files = {'activate.bat': ACTIVATE_BAT, | ||
961 | 'deactivate.bat': DEACTIVATE_BAT} | ||
962 | if os.environ.get('OS') == 'Windows_NT' and os.environ.get('OSTYPE') == 'cygwin': | ||
963 | files['activate'] = ACTIVATE_SH | ||
964 | else: | ||
965 | files = {'activate': ACTIVATE_SH} | ||
966 | |||
967 | # suppling activate.fish in addition to, not instead of, the | ||
968 | # bash script support. | ||
969 | files['activate.fish'] = ACTIVATE_FISH | ||
970 | |||
971 | # same for csh/tcsh support... | ||
972 | files['activate.csh'] = ACTIVATE_CSH | ||
973 | |||
974 | |||
975 | |||
976 | files['activate_this.py'] = ACTIVATE_THIS | ||
977 | vname = os.path.basename(os.path.abspath(home_dir)) | ||
978 | for name, content in files.items(): | ||
979 | content = content.replace('__VIRTUAL_PROMPT__', prompt or '') | ||
980 | content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) | ||
981 | content = content.replace('__VIRTUAL_ENV__', os.path.abspath(home_dir)) | ||
982 | content = content.replace('__VIRTUAL_NAME__', vname) | ||
983 | content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) | ||
984 | writefile(os.path.join(bin_dir, name), content) | ||
985 | |||
986 | def install_distutils(home_dir): | ||
987 | distutils_path = change_prefix(distutils.__path__[0], home_dir) | ||
988 | mkdir(distutils_path) | ||
989 | ## FIXME: maybe this prefix setting should only be put in place if | ||
990 | ## there's a local distutils.cfg with a prefix setting? | ||
991 | home_dir = os.path.abspath(home_dir) | ||
992 | ## FIXME: this is breaking things, removing for now: | ||
993 | #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir | ||
994 | writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) | ||
995 | writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) | ||
996 | |||
997 | def fix_lib64(lib_dir): | ||
998 | """ | ||
999 | Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y | ||
1000 | instead of lib/pythonX.Y. If this is such a platform we'll just create a | ||
1001 | symlink so lib64 points to lib | ||
1002 | """ | ||
1003 | if [p for p in distutils.sysconfig.get_config_vars().values() | ||
1004 | if isinstance(p, basestring) and 'lib64' in p]: | ||
1005 | logger.debug('This system uses lib64; symlinking lib64 to lib') | ||
1006 | assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( | ||
1007 | "Unexpected python lib dir: %r" % lib_dir) | ||
1008 | lib_parent = os.path.dirname(lib_dir) | ||
1009 | assert os.path.basename(lib_parent) == 'lib', ( | ||
1010 | "Unexpected parent dir: %r" % lib_parent) | ||
1011 | copyfile(lib_parent, os.path.join(os.path.dirname(lib_parent), 'lib64')) | ||
1012 | |||
1013 | def resolve_interpreter(exe): | ||
1014 | """ | ||
1015 | If the executable given isn't an absolute path, search $PATH for the interpreter | ||
1016 | """ | ||
1017 | if os.path.abspath(exe) != exe: | ||
1018 | paths = os.environ.get('PATH', '').split(os.pathsep) | ||
1019 | for path in paths: | ||
1020 | if os.path.exists(os.path.join(path, exe)): | ||
1021 | exe = os.path.join(path, exe) | ||
1022 | break | ||
1023 | if not os.path.exists(exe): | ||
1024 | logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) | ||
1025 | sys.exit(3) | ||
1026 | return exe | ||
1027 | |||
1028 | ############################################################ | ||
1029 | ## Relocating the environment: | ||
1030 | |||
1031 | def make_environment_relocatable(home_dir): | ||
1032 | """ | ||
1033 | Makes the already-existing environment use relative paths, and takes out | ||
1034 | the #!-based environment selection in scripts. | ||
1035 | """ | ||
1036 | home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | ||
1037 | activate_this = os.path.join(bin_dir, 'activate_this.py') | ||
1038 | if not os.path.exists(activate_this): | ||
1039 | logger.fatal( | ||
1040 | 'The environment doesn\'t have a file %s -- please re-run virtualenv ' | ||
1041 | 'on this environment to update it' % activate_this) | ||
1042 | fixup_scripts(home_dir) | ||
1043 | fixup_pth_and_egg_link(home_dir) | ||
1044 | ## FIXME: need to fix up distutils.cfg | ||
1045 | |||
1046 | OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], | ||
1047 | 'activate', 'activate.bat', 'activate_this.py'] | ||
1048 | |||
1049 | def fixup_scripts(home_dir): | ||
1050 | # This is what we expect at the top of scripts: | ||
1051 | shebang = '#!%s/bin/python' % os.path.normcase(os.path.abspath(home_dir)) | ||
1052 | # This is what we'll put: | ||
1053 | new_shebang = '#!/usr/bin/env python%s' % sys.version[:3] | ||
1054 | activate = "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this" | ||
1055 | if sys.platform == 'win32': | ||
1056 | bin_suffix = 'Scripts' | ||
1057 | else: | ||
1058 | bin_suffix = 'bin' | ||
1059 | bin_dir = os.path.join(home_dir, bin_suffix) | ||
1060 | home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | ||
1061 | for filename in os.listdir(bin_dir): | ||
1062 | filename = os.path.join(bin_dir, filename) | ||
1063 | if not os.path.isfile(filename): | ||
1064 | # ignore subdirs, e.g. .svn ones. | ||
1065 | continue | ||
1066 | f = open(filename, 'rb') | ||
1067 | lines = f.readlines() | ||
1068 | f.close() | ||
1069 | if not lines: | ||
1070 | logger.warn('Script %s is an empty file' % filename) | ||
1071 | continue | ||
1072 | if not lines[0].strip().startswith(shebang): | ||
1073 | if os.path.basename(filename) in OK_ABS_SCRIPTS: | ||
1074 | logger.debug('Cannot make script %s relative' % filename) | ||
1075 | elif lines[0].strip() == new_shebang: | ||
1076 | logger.info('Script %s has already been made relative' % filename) | ||
1077 | else: | ||
1078 | logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' | ||
1079 | % (filename, shebang)) | ||
1080 | continue | ||
1081 | logger.notify('Making script %s relative' % filename) | ||
1082 | lines = [new_shebang+'\n', activate+'\n'] + lines[1:] | ||
1083 | f = open(filename, 'wb') | ||
1084 | f.writelines(lines) | ||
1085 | f.close() | ||
1086 | |||
1087 | def fixup_pth_and_egg_link(home_dir, sys_path=None): | ||
1088 | """Makes .pth and .egg-link files use relative paths""" | ||
1089 | home_dir = os.path.normcase(os.path.abspath(home_dir)) | ||
1090 | if sys_path is None: | ||
1091 | sys_path = sys.path | ||
1092 | for path in sys_path: | ||
1093 | if not path: | ||
1094 | path = '.' | ||
1095 | if not os.path.isdir(path): | ||
1096 | continue | ||
1097 | path = os.path.normcase(os.path.abspath(path)) | ||
1098 | if not path.startswith(home_dir): | ||
1099 | logger.debug('Skipping system (non-environment) directory %s' % path) | ||
1100 | continue | ||
1101 | for filename in os.listdir(path): | ||
1102 | filename = os.path.join(path, filename) | ||
1103 | if filename.endswith('.pth'): | ||
1104 | if not os.access(filename, os.W_OK): | ||
1105 | logger.warn('Cannot write .pth file %s, skipping' % filename) | ||
1106 | else: | ||
1107 | fixup_pth_file(filename) | ||
1108 | if filename.endswith('.egg-link'): | ||
1109 | if not os.access(filename, os.W_OK): | ||
1110 | logger.warn('Cannot write .egg-link file %s, skipping' % filename) | ||
1111 | else: | ||
1112 | fixup_egg_link(filename) | ||
1113 | |||
1114 | def fixup_pth_file(filename): | ||
1115 | lines = [] | ||
1116 | prev_lines = [] | ||
1117 | f = open(filename) | ||
1118 | prev_lines = f.readlines() | ||
1119 | f.close() | ||
1120 | for line in prev_lines: | ||
1121 | line = line.strip() | ||
1122 | if (not line or line.startswith('#') or line.startswith('import ') | ||
1123 | or os.path.abspath(line) != line): | ||
1124 | lines.append(line) | ||
1125 | else: | ||
1126 | new_value = make_relative_path(filename, line) | ||
1127 | if line != new_value: | ||
1128 | logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) | ||
1129 | lines.append(new_value) | ||
1130 | if lines == prev_lines: | ||
1131 | logger.info('No changes to .pth file %s' % filename) | ||
1132 | return | ||
1133 | logger.notify('Making paths in .pth file %s relative' % filename) | ||
1134 | f = open(filename, 'w') | ||
1135 | f.write('\n'.join(lines) + '\n') | ||
1136 | f.close() | ||
1137 | |||
1138 | def fixup_egg_link(filename): | ||
1139 | f = open(filename) | ||
1140 | link = f.read().strip() | ||
1141 | f.close() | ||
1142 | if os.path.abspath(link) != link: | ||
1143 | logger.debug('Link in %s already relative' % filename) | ||
1144 | return | ||
1145 | new_link = make_relative_path(filename, link) | ||
1146 | logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) | ||
1147 | f = open(filename, 'w') | ||
1148 | f.write(new_link) | ||
1149 | f.close() | ||
1150 | |||
1151 | def make_relative_path(source, dest, dest_is_directory=True): | ||
1152 | """ | ||
1153 | Make a filename relative, where the filename is dest, and it is | ||
1154 | being referred to from the filename source. | ||
1155 | |||
1156 | >>> make_relative_path('/usr/share/something/a-file.pth', | ||
1157 | ... '/usr/share/another-place/src/Directory') | ||
1158 | '../another-place/src/Directory' | ||
1159 | >>> make_relative_path('/usr/share/something/a-file.pth', | ||
1160 | ... '/home/user/src/Directory') | ||
1161 | '../../../home/user/src/Directory' | ||
1162 | >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') | ||
1163 | './' | ||
1164 | """ | ||
1165 | source = os.path.dirname(source) | ||
1166 | if not dest_is_directory: | ||
1167 | dest_filename = os.path.basename(dest) | ||
1168 | dest = os.path.dirname(dest) | ||
1169 | dest = os.path.normpath(os.path.abspath(dest)) | ||
1170 | source = os.path.normpath(os.path.abspath(source)) | ||
1171 | dest_parts = dest.strip(os.path.sep).split(os.path.sep) | ||
1172 | source_parts = source.strip(os.path.sep).split(os.path.sep) | ||
1173 | while dest_parts and source_parts and dest_parts[0] == source_parts[0]: | ||
1174 | dest_parts.pop(0) | ||
1175 | source_parts.pop(0) | ||
1176 | full_parts = ['..']*len(source_parts) + dest_parts | ||
1177 | if not dest_is_directory: | ||
1178 | full_parts.append(dest_filename) | ||
1179 | if not full_parts: | ||
1180 | # Special case for the current directory (otherwise it'd be '') | ||
1181 | return './' | ||
1182 | return os.path.sep.join(full_parts) | ||
1183 | |||
1184 | |||
1185 | |||
1186 | ############################################################ | ||
1187 | ## Bootstrap script creation: | ||
1188 | |||
1189 | def create_bootstrap_script(extra_text, python_version=''): | ||
1190 | """ | ||
1191 | Creates a bootstrap script, which is like this script but with | ||
1192 | extend_parser, adjust_options, and after_install hooks. | ||
1193 | |||
1194 | This returns a string that (written to disk of course) can be used | ||
1195 | as a bootstrap script with your own customizations. The script | ||
1196 | will be the standard virtualenv.py script, with your extra text | ||
1197 | added (your extra text should be Python code). | ||
1198 | |||
1199 | If you include these functions, they will be called: | ||
1200 | |||
1201 | ``extend_parser(optparse_parser)``: | ||
1202 | You can add or remove options from the parser here. | ||
1203 | |||
1204 | ``adjust_options(options, args)``: | ||
1205 | You can change options here, or change the args (if you accept | ||
1206 | different kinds of arguments, be sure you modify ``args`` so it is | ||
1207 | only ``[DEST_DIR]``). | ||
1208 | |||
1209 | ``after_install(options, home_dir)``: | ||
1210 | |||
1211 | After everything is installed, this function is called. This | ||
1212 | is probably the function you are most likely to use. An | ||
1213 | example would be:: | ||
1214 | |||
1215 | def after_install(options, home_dir): | ||
1216 | subprocess.call([join(home_dir, 'bin', 'easy_install'), | ||
1217 | 'MyPackage']) | ||
1218 | subprocess.call([join(home_dir, 'bin', 'my-package-script'), | ||
1219 | 'setup', home_dir]) | ||
1220 | |||
1221 | This example immediately installs a package, and runs a setup | ||
1222 | script from that package. | ||
1223 | |||
1224 | If you provide something like ``python_version='2.4'`` then the | ||
1225 | script will start with ``#!/usr/bin/env python2.4`` instead of | ||
1226 | ``#!/usr/bin/env python``. You can use this when the script must | ||
1227 | be run with a particular Python version. | ||
1228 | """ | ||
1229 | filename = __file__ | ||
1230 | if filename.endswith('.pyc'): | ||
1231 | filename = filename[:-1] | ||
1232 | f = open(filename, 'rb') | ||
1233 | content = f.read() | ||
1234 | f.close() | ||
1235 | py_exe = 'python%s' % python_version | ||
1236 | content = (('#!/usr/bin/env %s\n' % py_exe) | ||
1237 | + '## WARNING: This file is generated\n' | ||
1238 | + content) | ||
1239 | return content.replace('##EXT' 'END##', extra_text) | ||
1240 | |||
1241 | # | ||
1242 | # Copyright 2010 Leonard Thomas | ||
1243 | # | ||
1244 | # This file is part of Dodai. | ||
1245 | # | ||
1246 | # Dodai is free software: you can redistribute it and/or modify | ||
1247 | # it under the terms of the GNU General Public License as published by | ||
1248 | # the Free Software Foundation, either version 3 of the License, or | ||
1249 | # (at your option) any later version. | ||
1250 | # | ||
1251 | # Dodai is distributed in the hope that it will be useful, | ||
1252 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
1253 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
1254 | # GNU General Public License for more details. | ||
1255 | # | ||
1256 | # You should have received a copy of the GNU General Public License | ||
1257 | # along with Dodai. If not, see <http://www.gnu.org/licenses/>. | ||
1258 | |||
1259 | |||
1260 | |||
1261 | import os | ||
1262 | from collections import namedtuple | ||
1263 | from subprocess import Popen | ||
1264 | from subprocess import call | ||
1265 | from subprocess import PIPE | ||
1266 | |||
1267 | def build_paths(home_dir): | ||
1268 | |||
1269 | obj = namedtuple('Paths', 'wd, home, bin, src, python') | ||
1270 | |||
1271 | wd = os.getcwd() | ||
1272 | if home_dir.startswith(os.sep): | ||
1273 | home = home_dir | ||
1274 | else: | ||
1275 | home = os.path.realpath(os.path.join(wd, home_dir)) | ||
1276 | bin = os.path.join(home, 'bin') | ||
1277 | src = os.path.join(home, 'src') | ||
1278 | python = os.path.join(bin, 'python') | ||
1279 | |||
1280 | return obj(wd, home, bin, src, python) | ||
1281 | |||
1282 | |||
1283 | class EasyInstall(object): | ||
1284 | |||
1285 | def __init__(self, paths): | ||
1286 | self._easy_install = os.path.join(paths.bin, 'easy_install') | ||
1287 | |||
1288 | def __call__(self, package): | ||
1289 | cmd = [self._easy_install, '-Uv', package] | ||
1290 | call(cmd) | ||
1291 | |||
1292 | |||
1293 | class HgClone(object): | ||
1294 | |||
1295 | def __init__(self, paths, easy_install=EasyInstall): | ||
1296 | self._easy_install = easy_install(paths) | ||
1297 | self._paths = paths | ||
1298 | self._hg_ = None | ||
1299 | |||
1300 | @property | ||
1301 | def _hg(self): | ||
1302 | if not self._hg_: | ||
1303 | cmd = ['which', 'hg'] | ||
1304 | self._hg_ = Popen(cmd, stdout=PIPE, stderr=PIPE).communicate()[0]\ | ||
1305 | .strip() | ||
1306 | if not self._hg_: | ||
1307 | self._hg_ = os.path.join(self._paths.bin, 'hg') | ||
1308 | if not os.path.exists(self._hg_): | ||
1309 | self._easy_install('mercurial') | ||
1310 | self._hg_ = os.path.join(self._paths.bin, 'hg') | ||
1311 | return self._hg_ | ||
1312 | |||
1313 | def __call__(self, url, dest): | ||
1314 | if not dest.startswith(os.sep): | ||
1315 | dest = os.path.join(self._paths.home, dest) | ||
1316 | cmd = [self._hg, 'clone', url, dest] | ||
1317 | call(cmd) | ||
1318 | |||
1319 | |||
1320 | class SetupPy(object): | ||
1321 | |||
1322 | FILE = 'setup.py' | ||
1323 | |||
1324 | def __init__(self, paths): | ||
1325 | self._paths = paths | ||
1326 | |||
1327 | def __call__(self, dir, command): | ||
1328 | path = os.path.join(self._paths.home, dir) | ||
1329 | name = os.path.join(path, self.FILE) | ||
1330 | if os.path.exists(name): | ||
1331 | os.chdir(path) | ||
1332 | cmd = [self._paths.python, name, command] | ||
1333 | call(cmd) | ||
1334 | |||
1335 | class RunPythonProgram(object): | ||
1336 | |||
1337 | def __init__(self, paths): | ||
1338 | self._paths = paths | ||
1339 | |||
1340 | def __call__(self, program): | ||
1341 | path = os.path.join(self._paths.bin, program) | ||
1342 | if os.path.exists(path): | ||
1343 | cmd = [self._paths.python, path] | ||
1344 | call(cmd) | ||
1345 | |||
1346 | |||
1347 | def after_install(options, home_dir): | ||
1348 | paths = build_paths(home_dir) | ||
1349 | easy_install = EasyInstall(paths) | ||
1350 | hg_clone = HgClone(paths) | ||
1351 | setup_py = SetupPy(paths) | ||
1352 | run_program = RunPythonProgram(paths) | ||
1353 | for package in ['nose', 'virtualenv', 'ipython', 'pylint']: | ||
1354 | easy_install(package) | ||
1355 | hg_clone('https://dodai.googlecode.com/hg/', 'src') | ||
1356 | for dir in ['src']: | ||
1357 | setup_py(dir, 'develop') | ||
1358 | for program in []: | ||
1359 | run_program(program) | ||
1360 | |||
1361 | ##file site.py | ||
1362 | SITE_PY = """ | ||
1363 | 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 | ||
1496 | """.decode("base64").decode("zlib") | ||
1497 | |||
1498 | ##file ez_setup.py | ||
1499 | EZ_SETUP_PY = """ | ||
1500 | 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 | ||
1566 | 178BYnMUkw== | ||
1567 | """.decode("base64").decode("zlib") | ||
1568 | |||
1569 | ##file distribute_setup.py | ||
1570 | DISTRIBUTE_SETUP_PY = """ | ||
1571 | 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 | ||
1650 | """.decode("base64").decode("zlib") | ||
1651 | |||
1652 | ##file activate.sh | ||
1653 | ACTIVATE_SH = """ | ||
1654 | eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9 | ||
1655 | H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq | ||
1656 | DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs | ||
1657 | cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY | ||
1658 | G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T | ||
1659 | EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs | ||
1660 | wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG | ||
1661 | 5eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/ | ||
1662 | JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR | ||
1663 | huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx | ||
1664 | Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L | ||
1665 | Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw | ||
1666 | WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX | ||
1667 | LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2 | ||
1668 | """.decode("base64").decode("zlib") | ||
1669 | |||
1670 | ##file activate.fish | ||
1671 | ACTIVATE_FISH = """ | ||
1672 | eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A | ||
1673 | Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7 | ||
1674 | pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ | ||
1675 | lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v | ||
1676 | g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u | ||
1677 | grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS | ||
1678 | xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV | ||
1679 | MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu | ||
1680 | H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM | ||
1681 | L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz | ||
1682 | fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV | ||
1683 | pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh | ||
1684 | MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT | ||
1685 | O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz | ||
1686 | 7SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi | ||
1687 | m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq | ||
1688 | djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5 | ||
1689 | mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN | ||
1690 | jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk= | ||
1691 | """.decode("base64").decode("zlib") | ||
1692 | |||
1693 | ##file activate.csh | ||
1694 | ACTIVATE_CSH = """ | ||
1695 | eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49 | ||
1696 | XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp | ||
1697 | kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u | ||
1698 | pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx | ||
1699 | sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM | ||
1700 | yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu | ||
1701 | E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF | ||
1702 | lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7 | ||
1703 | r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo= | ||
1704 | """.decode("base64").decode("zlib") | ||
1705 | |||
1706 | ##file activate.bat | ||
1707 | ACTIVATE_BAT = """ | ||
1708 | eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8 | ||
1709 | qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug | ||
1710 | sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU | ||
1711 | ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu | ||
1712 | """.decode("base64").decode("zlib") | ||
1713 | |||
1714 | ##file deactivate.bat | ||
1715 | DEACTIVATE_BAT = """ | ||
1716 | eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q | ||
1717 | FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL | ||
1718 | i2dASrm4rFz9XLgAwJNbyQ== | ||
1719 | """.decode("base64").decode("zlib") | ||
1720 | |||
1721 | ##file distutils-init.py | ||
1722 | DISTUTILS_INIT = """ | ||
1723 | eJytV92L4zYQf9dfMU0ottuse/TeFkKh3MvC0Ydy0IdlMVpbTtR1JCMpm+T++s5Y/pBs53oPZ1hQ | ||
1724 | pPnSb34zo5WnVhsH2jLpV/Y2Li/cKKkOFoYN3Za6ErAdFtKC0g44vEvjzrwR6h1Oujo3YgdWw0VA | ||
1725 | yRWcLUo6cBpqqSpwRwHWVY18ZRB9W3jq3HDlfoIvqK7NG2gF7a297VANvZ3O1sGrQI/eDe5yB0ZY | ||
1726 | WQkLUpHxhVX09NDe3FGr31BL1lJUD9f8ln+FShpROm1ujOFS8ZOAPUKRt9wd836Hjqw7O9nYgvYD | ||
1727 | iX+1VOlMPPXQ5EVRy0YURbaDZDSQZEzWo7rS5kSLNHaQwX4RRLrQGe1nj92Fh1zltEhHDDZfEO0g | ||
1728 | O6MraHn5xg8IpYOfLfC2FdxYShLC64EES4A0uuROYhq49Zs368RpMvTHJmOiscKHUXRXKIpcKiuM | ||
1729 | Sz/sYHa7TkxcRYkkEhN8HZaxKCJXFFJJh+baW5JluRG8SjM20JHEA9qWWtXywBjbbvF2rjzC61k2 | ||
1730 | VSGuDibTUGlhVeLgTekLHPEP73wQrrscUsUGrPCGjkTCC1JXXyw8EJWP3FSUZY8IiSCCRp97dnfO | ||
1731 | RUUx5a0RtbxSzLX/3XBXYxIpyQka/fh74pGrjQ5QzUt9OnFV5dMV+otOG5gQjctxozNTNtzaSSiN | ||
1732 | JHqu0FeJmsqRN/KrKHRLGbaQWtHUgRB9FDfu5giN4eZWIDqWCv8vrcTjrNZgRXQPzy+RmGjQpLRI | ||
1733 | EKz0UqQLlR28ciusM8jn7PtcLPZy2zbSDeyyos0iO+ybBgPyRvSk/CEFm8IndQebz8iXTRbbjhDP | ||
1734 | 5xh7iJfBrKd/Nenjj6Jvgp2B+W7AnP102BXH5IZWPV3tI2MUOvXowpdS12IIXhLLP0lKyeuZrpEv | ||
1735 | pFhPqHg3JFTd1cceVp0EsPgGU0wFO2u4iyYRoFYfEm9kG/RZcUUBm87t9mFtx9iCtC9kx4Rt4R8a | ||
1736 | OdgzSt40vtyFecAZZ8BfCOhCrC8djMGPFaz2Vlt5TSZCk053+37wbLDLRXfZ+F45NtdVpVWdudSC | ||
1737 | xgODI8EsiLoTl5aO0lhoigX7GHZDHAY4LxoMIu1gXPYPksmFquxF4uRKZhEnKzXu82HESb+LlNQz | ||
1738 | Fh/RvFJVuhK+Ee5slBdj30FcRGdJ5rhKxtkyKxWcGoV/WOCYKqkNDYJ5fNQVx3g400tpJBS2FSU+ | ||
1739 | Tco9ss8nZ08dtscGQfSby87b73fOw+4UgrEMNnY6uMzYvSDxPVPpsij6+l0/ZPfuH0Iz010giY34 | ||
1740 | HpL0ZLyLJB4ukaQRU+GwptO7yIZCQE33B0K9iCqO6X+AR4n7wAeH68DPkJzpTsD3x+/cj9LIVHC2 | ||
1741 | An1wmv7CzWHoqR02vb0VL73siP+3nkX0YbQ0l9f6WDyOm24cj3rxO2MMip6kpcu6VCefn/789PR3 | ||
1742 | 0v0fg21sFIp70rj9PCi8YDRDXFucym/43qN+iENh1Jy/dIIIqF3OIkDvBMsdx+huWv8Kz73vl8g5 | ||
1743 | WQ3JOGqwu3lb4dfKKbvLigXDQsb8B/xt39Q= | ||
1744 | """.decode("base64").decode("zlib") | ||
1745 | |||
1746 | ##file distutils.cfg | ||
1747 | DISTUTILS_CFG = """ | ||
1748 | eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH | ||
1749 | xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg | ||
1750 | 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= | ||
1751 | """.decode("base64").decode("zlib") | ||
1752 | |||
1753 | ##file activate_this.py | ||
1754 | ACTIVATE_THIS = """ | ||
1755 | eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ | ||
1756 | VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a | ||
1757 | Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE | ||
1758 | qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX | ||
1759 | 4lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7 | ||
1760 | HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n | ||
1761 | xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96 | ||
1762 | 1Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI | ||
1763 | 3vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU= | ||
1764 | """.decode("base64").decode("zlib") | ||
1765 | |||
1766 | if __name__ == '__main__': | ||
1767 | main() | ||
1768 | |||
1769 | ## TODO: | ||
1770 | ## Copy python.exe.manifest | ||
1771 | ## Monkeypatch distutils.sysconfig | ||