diff options
author | Mike Crute <mike@crute.us> | 2019-09-05 17:52:28 -0700 |
---|---|---|
committer | Mike Crute <mike@crute.us> | 2019-09-05 17:52:28 -0700 |
commit | 7e3b6a543890b57e2d795728711734dc2f60db5f (patch) | |
tree | aaa10c0216b22e84630195f3b3b38294037d76e3 /bin | |
parent | cac339bed31b3c494b6aa2f161c1f8c7211e7dbd (diff) | |
download | dotfiles-7e3b6a543890b57e2d795728711734dc2f60db5f.tar.bz2 dotfiles-7e3b6a543890b57e2d795728711734dc2f60db5f.tar.xz dotfiles-7e3b6a543890b57e2d795728711734dc2f60db5f.zip |
Drop python2 virtualenv
Diffstat (limited to 'bin')
-rwxr-xr-x | bin/virtualenv | 2339 |
1 files changed, 0 insertions, 2339 deletions
diff --git a/bin/virtualenv b/bin/virtualenv deleted file mode 100755 index e451f16..0000000 --- a/bin/virtualenv +++ /dev/null | |||
@@ -1,2339 +0,0 @@ | |||
1 | #!/usr/bin/env python | ||
2 | """Create a "virtual" Python installation""" | ||
3 | |||
4 | import os | ||
5 | import sys | ||
6 | |||
7 | # If we are running in a new interpreter to create a virtualenv, | ||
8 | # we do NOT want paths from our existing location interfering with anything, | ||
9 | # So we remove this file's directory from sys.path - most likely to be | ||
10 | # the previous interpreter's site-packages. Solves #705, #763, #779 | ||
11 | if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): | ||
12 | for path in sys.path[:]: | ||
13 | if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path): | ||
14 | sys.path.remove(path) | ||
15 | |||
16 | import base64 | ||
17 | import codecs | ||
18 | import optparse | ||
19 | import re | ||
20 | import shutil | ||
21 | import logging | ||
22 | import zlib | ||
23 | import errno | ||
24 | import glob | ||
25 | import distutils.sysconfig | ||
26 | import struct | ||
27 | import subprocess | ||
28 | import pkgutil | ||
29 | import tempfile | ||
30 | import textwrap | ||
31 | from distutils.util import strtobool | ||
32 | from os.path import join | ||
33 | |||
34 | try: | ||
35 | import ConfigParser | ||
36 | except ImportError: | ||
37 | import configparser as ConfigParser | ||
38 | |||
39 | __version__ = "15.1.0.dev0" | ||
40 | virtualenv_version = __version__ # legacy | ||
41 | |||
42 | if sys.version_info < (2, 6): | ||
43 | print('ERROR: %s' % sys.exc_info()[1]) | ||
44 | print('ERROR: this script requires Python 2.6 or greater.') | ||
45 | sys.exit(101) | ||
46 | |||
47 | try: | ||
48 | basestring | ||
49 | except NameError: | ||
50 | basestring = str | ||
51 | |||
52 | py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) | ||
53 | |||
54 | is_jython = sys.platform.startswith('java') | ||
55 | is_pypy = hasattr(sys, 'pypy_version_info') | ||
56 | is_win = (sys.platform == 'win32') | ||
57 | is_cygwin = (sys.platform == 'cygwin') | ||
58 | is_darwin = (sys.platform == 'darwin') | ||
59 | abiflags = getattr(sys, 'abiflags', '') | ||
60 | |||
61 | user_dir = os.path.expanduser('~') | ||
62 | if is_win: | ||
63 | default_storage_dir = os.path.join(user_dir, 'virtualenv') | ||
64 | else: | ||
65 | default_storage_dir = os.path.join(user_dir, '.virtualenv') | ||
66 | default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini') | ||
67 | |||
68 | if is_pypy: | ||
69 | expected_exe = 'pypy' | ||
70 | elif is_jython: | ||
71 | expected_exe = 'jython' | ||
72 | else: | ||
73 | expected_exe = 'python' | ||
74 | |||
75 | # Return a mapping of version -> Python executable | ||
76 | # Only provided for Windows, where the information in the registry is used | ||
77 | if not is_win: | ||
78 | def get_installed_pythons(): | ||
79 | return {} | ||
80 | else: | ||
81 | try: | ||
82 | import winreg | ||
83 | except ImportError: | ||
84 | import _winreg as winreg | ||
85 | |||
86 | def get_installed_pythons(): | ||
87 | try: | ||
88 | python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, | ||
89 | "Software\\Python\\PythonCore") | ||
90 | except WindowsError: | ||
91 | # No registered Python installations | ||
92 | return {} | ||
93 | i = 0 | ||
94 | versions = [] | ||
95 | while True: | ||
96 | try: | ||
97 | versions.append(winreg.EnumKey(python_core, i)) | ||
98 | i = i + 1 | ||
99 | except WindowsError: | ||
100 | break | ||
101 | exes = dict() | ||
102 | for ver in versions: | ||
103 | try: | ||
104 | path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver) | ||
105 | except WindowsError: | ||
106 | continue | ||
107 | exes[ver] = join(path, "python.exe") | ||
108 | |||
109 | winreg.CloseKey(python_core) | ||
110 | |||
111 | # Add the major versions | ||
112 | # Sort the keys, then repeatedly update the major version entry | ||
113 | # Last executable (i.e., highest version) wins with this approach | ||
114 | for ver in sorted(exes): | ||
115 | exes[ver[0]] = exes[ver] | ||
116 | |||
117 | return exes | ||
118 | |||
119 | REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath', | ||
120 | 'fnmatch', 'locale', 'encodings', 'codecs', | ||
121 | 'stat', 'UserDict', 'readline', 'copy_reg', 'types', | ||
122 | 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile', | ||
123 | 'zlib'] | ||
124 | |||
125 | REQUIRED_FILES = ['lib-dynload', 'config'] | ||
126 | |||
127 | majver, minver = sys.version_info[:2] | ||
128 | if majver == 2: | ||
129 | if minver >= 6: | ||
130 | REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) | ||
131 | if minver >= 7: | ||
132 | REQUIRED_MODULES.extend(['_weakrefset']) | ||
133 | elif majver == 3: | ||
134 | # Some extra modules are needed for Python 3, but different ones | ||
135 | # for different versions. | ||
136 | REQUIRED_MODULES.extend([ | ||
137 | '_abcoll', 'warnings', 'linecache', 'abc', 'io', '_weakrefset', | ||
138 | 'copyreg', 'tempfile', 'random', '__future__', 'collections', | ||
139 | 'keyword', 'tarfile', 'shutil', 'struct', 'copy', 'tokenize', | ||
140 | 'token', 'functools', 'heapq', 'bisect', 'weakref', 'reprlib' | ||
141 | ]) | ||
142 | if minver >= 2: | ||
143 | REQUIRED_FILES[-1] = 'config-%s' % majver | ||
144 | if minver >= 3: | ||
145 | import sysconfig | ||
146 | platdir = sysconfig.get_config_var('PLATDIR') | ||
147 | REQUIRED_FILES.append(platdir) | ||
148 | REQUIRED_MODULES.extend([ | ||
149 | 'base64', '_dummy_thread', 'hashlib', 'hmac', | ||
150 | 'imp', 'importlib', 'rlcompleter' | ||
151 | ]) | ||
152 | if minver >= 4: | ||
153 | REQUIRED_MODULES.extend([ | ||
154 | 'operator', | ||
155 | '_collections_abc', | ||
156 | '_bootlocale', | ||
157 | ]) | ||
158 | |||
159 | if is_pypy: | ||
160 | # these are needed to correctly display the exceptions that may happen | ||
161 | # during the bootstrap | ||
162 | REQUIRED_MODULES.extend(['traceback', 'linecache']) | ||
163 | |||
164 | if majver == 3: | ||
165 | # _functools is needed to import locale during stdio initialization and | ||
166 | # needs to be copied on PyPy because it's not built in | ||
167 | REQUIRED_MODULES.append('_functools') | ||
168 | |||
169 | |||
170 | class Logger(object): | ||
171 | |||
172 | """ | ||
173 | Logging object for use in command-line script. Allows ranges of | ||
174 | levels, to avoid some redundancy of displayed information. | ||
175 | """ | ||
176 | |||
177 | DEBUG = logging.DEBUG | ||
178 | INFO = logging.INFO | ||
179 | NOTIFY = (logging.INFO+logging.WARN)/2 | ||
180 | WARN = WARNING = logging.WARN | ||
181 | ERROR = logging.ERROR | ||
182 | FATAL = logging.FATAL | ||
183 | |||
184 | LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] | ||
185 | |||
186 | def __init__(self, consumers): | ||
187 | self.consumers = consumers | ||
188 | self.indent = 0 | ||
189 | self.in_progress = None | ||
190 | self.in_progress_hanging = False | ||
191 | |||
192 | def debug(self, msg, *args, **kw): | ||
193 | self.log(self.DEBUG, msg, *args, **kw) | ||
194 | |||
195 | def info(self, msg, *args, **kw): | ||
196 | self.log(self.INFO, msg, *args, **kw) | ||
197 | |||
198 | def notify(self, msg, *args, **kw): | ||
199 | self.log(self.NOTIFY, msg, *args, **kw) | ||
200 | |||
201 | def warn(self, msg, *args, **kw): | ||
202 | self.log(self.WARN, msg, *args, **kw) | ||
203 | |||
204 | def error(self, msg, *args, **kw): | ||
205 | self.log(self.ERROR, msg, *args, **kw) | ||
206 | |||
207 | def fatal(self, msg, *args, **kw): | ||
208 | self.log(self.FATAL, msg, *args, **kw) | ||
209 | |||
210 | def log(self, level, msg, *args, **kw): | ||
211 | if args: | ||
212 | if kw: | ||
213 | raise TypeError( | ||
214 | "You may give positional or keyword arguments, not both") | ||
215 | args = args or kw | ||
216 | rendered = None | ||
217 | for consumer_level, consumer in self.consumers: | ||
218 | if self.level_matches(level, consumer_level): | ||
219 | if (self.in_progress_hanging | ||
220 | and consumer in (sys.stdout, sys.stderr)): | ||
221 | self.in_progress_hanging = False | ||
222 | sys.stdout.write('\n') | ||
223 | sys.stdout.flush() | ||
224 | if rendered is None: | ||
225 | if args: | ||
226 | rendered = msg % args | ||
227 | else: | ||
228 | rendered = msg | ||
229 | rendered = ' '*self.indent + rendered | ||
230 | if hasattr(consumer, 'write'): | ||
231 | consumer.write(rendered+'\n') | ||
232 | else: | ||
233 | consumer(rendered) | ||
234 | |||
235 | def start_progress(self, msg): | ||
236 | assert not self.in_progress, ( | ||
237 | "Tried to start_progress(%r) while in_progress %r" | ||
238 | % (msg, self.in_progress)) | ||
239 | if self.level_matches(self.NOTIFY, self._stdout_level()): | ||
240 | sys.stdout.write(msg) | ||
241 | sys.stdout.flush() | ||
242 | self.in_progress_hanging = True | ||
243 | else: | ||
244 | self.in_progress_hanging = False | ||
245 | self.in_progress = msg | ||
246 | |||
247 | def end_progress(self, msg='done.'): | ||
248 | assert self.in_progress, ( | ||
249 | "Tried to end_progress without start_progress") | ||
250 | if self.stdout_level_matches(self.NOTIFY): | ||
251 | if not self.in_progress_hanging: | ||
252 | # Some message has been printed out since start_progress | ||
253 | sys.stdout.write('...' + self.in_progress + msg + '\n') | ||
254 | sys.stdout.flush() | ||
255 | else: | ||
256 | sys.stdout.write(msg + '\n') | ||
257 | sys.stdout.flush() | ||
258 | self.in_progress = None | ||
259 | self.in_progress_hanging = False | ||
260 | |||
261 | def show_progress(self): | ||
262 | """If we are in a progress scope, and no log messages have been | ||
263 | shown, write out another '.'""" | ||
264 | if self.in_progress_hanging: | ||
265 | sys.stdout.write('.') | ||
266 | sys.stdout.flush() | ||
267 | |||
268 | def stdout_level_matches(self, level): | ||
269 | """Returns true if a message at this level will go to stdout""" | ||
270 | return self.level_matches(level, self._stdout_level()) | ||
271 | |||
272 | def _stdout_level(self): | ||
273 | """Returns the level that stdout runs at""" | ||
274 | for level, consumer in self.consumers: | ||
275 | if consumer is sys.stdout: | ||
276 | return level | ||
277 | return self.FATAL | ||
278 | |||
279 | def level_matches(self, level, consumer_level): | ||
280 | """ | ||
281 | >>> l = Logger([]) | ||
282 | >>> l.level_matches(3, 4) | ||
283 | False | ||
284 | >>> l.level_matches(3, 2) | ||
285 | True | ||
286 | >>> l.level_matches(slice(None, 3), 3) | ||
287 | False | ||
288 | >>> l.level_matches(slice(None, 3), 2) | ||
289 | True | ||
290 | >>> l.level_matches(slice(1, 3), 1) | ||
291 | True | ||
292 | >>> l.level_matches(slice(2, 3), 1) | ||
293 | False | ||
294 | """ | ||
295 | if isinstance(level, slice): | ||
296 | start, stop = level.start, level.stop | ||
297 | if start is not None and start > consumer_level: | ||
298 | return False | ||
299 | if stop is not None and stop <= consumer_level: | ||
300 | return False | ||
301 | return True | ||
302 | else: | ||
303 | return level >= consumer_level | ||
304 | |||
305 | #@classmethod | ||
306 | def level_for_integer(cls, level): | ||
307 | levels = cls.LEVELS | ||
308 | if level < 0: | ||
309 | return levels[0] | ||
310 | if level >= len(levels): | ||
311 | return levels[-1] | ||
312 | return levels[level] | ||
313 | |||
314 | level_for_integer = classmethod(level_for_integer) | ||
315 | |||
316 | # create a silent logger just to prevent this from being undefined | ||
317 | # will be overridden with requested verbosity main() is called. | ||
318 | logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) | ||
319 | |||
320 | def mkdir(path): | ||
321 | if not os.path.exists(path): | ||
322 | logger.info('Creating %s', path) | ||
323 | os.makedirs(path) | ||
324 | else: | ||
325 | logger.info('Directory %s already exists', path) | ||
326 | |||
327 | def copyfileordir(src, dest, symlink=True): | ||
328 | if os.path.isdir(src): | ||
329 | shutil.copytree(src, dest, symlink) | ||
330 | else: | ||
331 | shutil.copy2(src, dest) | ||
332 | |||
333 | def copyfile(src, dest, symlink=True): | ||
334 | if not os.path.exists(src): | ||
335 | # Some bad symlink in the src | ||
336 | logger.warn('Cannot find file %s (bad symlink)', src) | ||
337 | return | ||
338 | if os.path.exists(dest): | ||
339 | logger.debug('File %s already exists', dest) | ||
340 | return | ||
341 | if not os.path.exists(os.path.dirname(dest)): | ||
342 | logger.info('Creating parent directories for %s', os.path.dirname(dest)) | ||
343 | os.makedirs(os.path.dirname(dest)) | ||
344 | if not os.path.islink(src): | ||
345 | srcpath = os.path.abspath(src) | ||
346 | else: | ||
347 | srcpath = os.readlink(src) | ||
348 | if symlink and hasattr(os, 'symlink') and not is_win: | ||
349 | logger.info('Symlinking %s', dest) | ||
350 | try: | ||
351 | os.symlink(srcpath, dest) | ||
352 | except (OSError, NotImplementedError): | ||
353 | logger.info('Symlinking failed, copying to %s', dest) | ||
354 | copyfileordir(src, dest, symlink) | ||
355 | else: | ||
356 | logger.info('Copying to %s', dest) | ||
357 | copyfileordir(src, dest, symlink) | ||
358 | |||
359 | def writefile(dest, content, overwrite=True): | ||
360 | if not os.path.exists(dest): | ||
361 | logger.info('Writing %s', dest) | ||
362 | with open(dest, 'wb') as f: | ||
363 | f.write(content.encode('utf-8')) | ||
364 | return | ||
365 | else: | ||
366 | with open(dest, 'rb') as f: | ||
367 | c = f.read() | ||
368 | if c != content.encode("utf-8"): | ||
369 | if not overwrite: | ||
370 | logger.notify('File %s exists with different content; not overwriting', dest) | ||
371 | return | ||
372 | logger.notify('Overwriting %s with new content', dest) | ||
373 | with open(dest, 'wb') as f: | ||
374 | f.write(content.encode('utf-8')) | ||
375 | else: | ||
376 | logger.info('Content %s already in place', dest) | ||
377 | |||
378 | def rmtree(dir): | ||
379 | if os.path.exists(dir): | ||
380 | logger.notify('Deleting tree %s', dir) | ||
381 | shutil.rmtree(dir) | ||
382 | else: | ||
383 | logger.info('Do not need to delete %s; already gone', dir) | ||
384 | |||
385 | def make_exe(fn): | ||
386 | if hasattr(os, 'chmod'): | ||
387 | oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777 | ||
388 | newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777 | ||
389 | os.chmod(fn, newmode) | ||
390 | logger.info('Changed mode of %s to %s', fn, oct(newmode)) | ||
391 | |||
392 | def _find_file(filename, dirs): | ||
393 | for dir in reversed(dirs): | ||
394 | files = glob.glob(os.path.join(dir, filename)) | ||
395 | if files and os.path.isfile(files[0]): | ||
396 | return True, files[0] | ||
397 | return False, filename | ||
398 | |||
399 | def file_search_dirs(): | ||
400 | here = os.path.dirname(os.path.abspath(__file__)) | ||
401 | dirs = [here, join(here, 'virtualenv_support'), | ||
402 | join(user_dir, '.virtualenv_support')] | ||
403 | if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': | ||
404 | # Probably some boot script; just in case virtualenv is installed... | ||
405 | try: | ||
406 | import virtualenv | ||
407 | except ImportError: | ||
408 | pass | ||
409 | else: | ||
410 | dirs.append(os.path.join( | ||
411 | os.path.dirname(virtualenv.__file__), 'virtualenv_support')) | ||
412 | return [d for d in dirs if os.path.isdir(d)] | ||
413 | |||
414 | |||
415 | class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): | ||
416 | """ | ||
417 | Custom help formatter for use in ConfigOptionParser that updates | ||
418 | the defaults before expanding them, allowing them to show up correctly | ||
419 | in the help listing | ||
420 | """ | ||
421 | def expand_default(self, option): | ||
422 | if self.parser is not None: | ||
423 | self.parser.update_defaults(self.parser.defaults) | ||
424 | return optparse.IndentedHelpFormatter.expand_default(self, option) | ||
425 | |||
426 | |||
427 | class ConfigOptionParser(optparse.OptionParser): | ||
428 | """ | ||
429 | Custom option parser which updates its defaults by checking the | ||
430 | configuration files and environmental variables | ||
431 | """ | ||
432 | def __init__(self, *args, **kwargs): | ||
433 | self.config = ConfigParser.RawConfigParser() | ||
434 | self.files = self.get_config_files() | ||
435 | self.config.read(self.files) | ||
436 | optparse.OptionParser.__init__(self, *args, **kwargs) | ||
437 | |||
438 | def get_config_files(self): | ||
439 | config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False) | ||
440 | if config_file and os.path.exists(config_file): | ||
441 | return [config_file] | ||
442 | return [default_config_file] | ||
443 | |||
444 | def update_defaults(self, defaults): | ||
445 | """ | ||
446 | Updates the given defaults with values from the config files and | ||
447 | the environ. Does a little special handling for certain types of | ||
448 | options (lists). | ||
449 | """ | ||
450 | # Then go and look for the other sources of configuration: | ||
451 | config = {} | ||
452 | # 1. config files | ||
453 | config.update(dict(self.get_config_section('virtualenv'))) | ||
454 | # 2. environmental variables | ||
455 | config.update(dict(self.get_environ_vars())) | ||
456 | # Then set the options with those values | ||
457 | for key, val in config.items(): | ||
458 | key = key.replace('_', '-') | ||
459 | if not key.startswith('--'): | ||
460 | key = '--%s' % key # only prefer long opts | ||
461 | option = self.get_option(key) | ||
462 | if option is not None: | ||
463 | # ignore empty values | ||
464 | if not val: | ||
465 | continue | ||
466 | # handle multiline configs | ||
467 | if option.action == 'append': | ||
468 | val = val.split() | ||
469 | else: | ||
470 | option.nargs = 1 | ||
471 | if option.action == 'store_false': | ||
472 | val = not strtobool(val) | ||
473 | elif option.action in ('store_true', 'count'): | ||
474 | val = strtobool(val) | ||
475 | try: | ||
476 | val = option.convert_value(key, val) | ||
477 | except optparse.OptionValueError: | ||
478 | e = sys.exc_info()[1] | ||
479 | print("An error occurred during configuration: %s" % e) | ||
480 | sys.exit(3) | ||
481 | defaults[option.dest] = val | ||
482 | return defaults | ||
483 | |||
484 | def get_config_section(self, name): | ||
485 | """ | ||
486 | Get a section of a configuration | ||
487 | """ | ||
488 | if self.config.has_section(name): | ||
489 | return self.config.items(name) | ||
490 | return [] | ||
491 | |||
492 | def get_environ_vars(self, prefix='VIRTUALENV_'): | ||
493 | """ | ||
494 | Returns a generator with all environmental vars with prefix VIRTUALENV | ||
495 | """ | ||
496 | for key, val in os.environ.items(): | ||
497 | if key.startswith(prefix): | ||
498 | yield (key.replace(prefix, '').lower(), val) | ||
499 | |||
500 | def get_default_values(self): | ||
501 | """ | ||
502 | Overridding to make updating the defaults after instantiation of | ||
503 | the option parser possible, update_defaults() does the dirty work. | ||
504 | """ | ||
505 | if not self.process_default_values: | ||
506 | # Old, pre-Optik 1.5 behaviour. | ||
507 | return optparse.Values(self.defaults) | ||
508 | |||
509 | defaults = self.update_defaults(self.defaults.copy()) # ours | ||
510 | for option in self._get_all_options(): | ||
511 | default = defaults.get(option.dest) | ||
512 | if isinstance(default, basestring): | ||
513 | opt_str = option.get_opt_string() | ||
514 | defaults[option.dest] = option.check_value(opt_str, default) | ||
515 | return optparse.Values(defaults) | ||
516 | |||
517 | |||
518 | def main(): | ||
519 | parser = ConfigOptionParser( | ||
520 | version=virtualenv_version, | ||
521 | usage="%prog [OPTIONS] DEST_DIR", | ||
522 | formatter=UpdatingDefaultsHelpFormatter()) | ||
523 | |||
524 | parser.add_option( | ||
525 | '-v', '--verbose', | ||
526 | action='count', | ||
527 | dest='verbose', | ||
528 | default=0, | ||
529 | help="Increase verbosity.") | ||
530 | |||
531 | parser.add_option( | ||
532 | '-q', '--quiet', | ||
533 | action='count', | ||
534 | dest='quiet', | ||
535 | default=0, | ||
536 | help='Decrease verbosity.') | ||
537 | |||
538 | parser.add_option( | ||
539 | '-p', '--python', | ||
540 | dest='python', | ||
541 | metavar='PYTHON_EXE', | ||
542 | help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 ' | ||
543 | 'interpreter to create the new environment. The default is the interpreter that ' | ||
544 | 'virtualenv was installed with (%s)' % sys.executable) | ||
545 | |||
546 | parser.add_option( | ||
547 | '--clear', | ||
548 | dest='clear', | ||
549 | action='store_true', | ||
550 | help="Clear out the non-root install and start from scratch.") | ||
551 | |||
552 | parser.set_defaults(system_site_packages=False) | ||
553 | parser.add_option( | ||
554 | '--no-site-packages', | ||
555 | dest='system_site_packages', | ||
556 | action='store_false', | ||
557 | help="DEPRECATED. Retained only for backward compatibility. " | ||
558 | "Not having access to global site-packages is now the default behavior.") | ||
559 | |||
560 | parser.add_option( | ||
561 | '--system-site-packages', | ||
562 | dest='system_site_packages', | ||
563 | action='store_true', | ||
564 | help="Give the virtual environment access to the global site-packages.") | ||
565 | |||
566 | parser.add_option( | ||
567 | '--always-copy', | ||
568 | dest='symlink', | ||
569 | action='store_false', | ||
570 | default=True, | ||
571 | help="Always copy files rather than symlinking.") | ||
572 | |||
573 | parser.add_option( | ||
574 | '--unzip-setuptools', | ||
575 | dest='unzip_setuptools', | ||
576 | action='store_true', | ||
577 | help="Unzip Setuptools when installing it.") | ||
578 | |||
579 | parser.add_option( | ||
580 | '--relocatable', | ||
581 | dest='relocatable', | ||
582 | action='store_true', | ||
583 | help='Make an EXISTING virtualenv environment relocatable. ' | ||
584 | 'This fixes up scripts and makes all .pth files relative.') | ||
585 | |||
586 | parser.add_option( | ||
587 | '--no-setuptools', | ||
588 | dest='no_setuptools', | ||
589 | action='store_true', | ||
590 | help='Do not install setuptools in the new virtualenv.') | ||
591 | |||
592 | parser.add_option( | ||
593 | '--no-pip', | ||
594 | dest='no_pip', | ||
595 | action='store_true', | ||
596 | help='Do not install pip in the new virtualenv.') | ||
597 | |||
598 | parser.add_option( | ||
599 | '--no-wheel', | ||
600 | dest='no_wheel', | ||
601 | action='store_true', | ||
602 | help='Do not install wheel in the new virtualenv.') | ||
603 | |||
604 | default_search_dirs = file_search_dirs() | ||
605 | parser.add_option( | ||
606 | '--extra-search-dir', | ||
607 | dest="search_dirs", | ||
608 | action="append", | ||
609 | metavar='DIR', | ||
610 | default=default_search_dirs, | ||
611 | help="Directory to look for setuptools/pip distributions in. " | ||
612 | "This option can be used multiple times.") | ||
613 | |||
614 | parser.add_option( | ||
615 | "--download", | ||
616 | dest="download", | ||
617 | default=True, | ||
618 | action="store_true", | ||
619 | help="Download preinstalled packages from PyPI.", | ||
620 | ) | ||
621 | |||
622 | parser.add_option( | ||
623 | "--no-download", | ||
624 | '--never-download', | ||
625 | dest="download", | ||
626 | action="store_false", | ||
627 | help="Do not download preinstalled packages from PyPI.", | ||
628 | ) | ||
629 | |||
630 | parser.add_option( | ||
631 | '--prompt', | ||
632 | dest='prompt', | ||
633 | help='Provides an alternative prompt prefix for this environment.') | ||
634 | |||
635 | parser.add_option( | ||
636 | '--setuptools', | ||
637 | dest='setuptools', | ||
638 | action='store_true', | ||
639 | help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") | ||
640 | |||
641 | parser.add_option( | ||
642 | '--distribute', | ||
643 | dest='distribute', | ||
644 | action='store_true', | ||
645 | help="DEPRECATED. Retained only for backward compatibility. This option has no effect.") | ||
646 | |||
647 | if 'extend_parser' in globals(): | ||
648 | extend_parser(parser) | ||
649 | |||
650 | options, args = parser.parse_args() | ||
651 | |||
652 | global logger | ||
653 | |||
654 | if 'adjust_options' in globals(): | ||
655 | adjust_options(options, args) | ||
656 | |||
657 | verbosity = options.verbose - options.quiet | ||
658 | logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)]) | ||
659 | |||
660 | if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): | ||
661 | env = os.environ.copy() | ||
662 | interpreter = resolve_interpreter(options.python) | ||
663 | if interpreter == sys.executable: | ||
664 | logger.warn('Already using interpreter %s' % interpreter) | ||
665 | else: | ||
666 | logger.notify('Running virtualenv with interpreter %s' % interpreter) | ||
667 | env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true' | ||
668 | file = __file__ | ||
669 | if file.endswith('.pyc'): | ||
670 | file = file[:-1] | ||
671 | popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env) | ||
672 | raise SystemExit(popen.wait()) | ||
673 | |||
674 | if not args: | ||
675 | print('You must provide a DEST_DIR') | ||
676 | parser.print_help() | ||
677 | sys.exit(2) | ||
678 | if len(args) > 1: | ||
679 | print('There must be only one argument: DEST_DIR (you gave %s)' % ( | ||
680 | ' '.join(args))) | ||
681 | parser.print_help() | ||
682 | sys.exit(2) | ||
683 | |||
684 | home_dir = args[0] | ||
685 | |||
686 | if os.path.exists(home_dir) and os.path.isfile(home_dir): | ||
687 | logger.fatal('ERROR: File already exists and is not a directory.') | ||
688 | logger.fatal('Please provide a different path or delete the file.') | ||
689 | sys.exit(3) | ||
690 | |||
691 | if os.environ.get('WORKING_ENV'): | ||
692 | logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') | ||
693 | logger.fatal('Please deactivate your workingenv, then re-run this script') | ||
694 | sys.exit(3) | ||
695 | |||
696 | if 'PYTHONHOME' in os.environ: | ||
697 | logger.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it') | ||
698 | del os.environ['PYTHONHOME'] | ||
699 | |||
700 | if options.relocatable: | ||
701 | make_environment_relocatable(home_dir) | ||
702 | return | ||
703 | |||
704 | create_environment(home_dir, | ||
705 | site_packages=options.system_site_packages, | ||
706 | clear=options.clear, | ||
707 | unzip_setuptools=options.unzip_setuptools, | ||
708 | prompt=options.prompt, | ||
709 | search_dirs=options.search_dirs, | ||
710 | download=options.download, | ||
711 | no_setuptools=options.no_setuptools, | ||
712 | no_pip=options.no_pip, | ||
713 | no_wheel=options.no_wheel, | ||
714 | symlink=options.symlink) | ||
715 | if 'after_install' in globals(): | ||
716 | after_install(options, home_dir) | ||
717 | |||
718 | def call_subprocess(cmd, show_stdout=True, | ||
719 | filter_stdout=None, cwd=None, | ||
720 | raise_on_returncode=True, extra_env=None, | ||
721 | remove_from_env=None, stdin=None): | ||
722 | cmd_parts = [] | ||
723 | for part in cmd: | ||
724 | if len(part) > 45: | ||
725 | part = part[:20]+"..."+part[-20:] | ||
726 | if ' ' in part or '\n' in part or '"' in part or "'" in part: | ||
727 | part = '"%s"' % part.replace('"', '\\"') | ||
728 | if hasattr(part, 'decode'): | ||
729 | try: | ||
730 | part = part.decode(sys.getdefaultencoding()) | ||
731 | except UnicodeDecodeError: | ||
732 | part = part.decode(sys.getfilesystemencoding()) | ||
733 | cmd_parts.append(part) | ||
734 | cmd_desc = ' '.join(cmd_parts) | ||
735 | if show_stdout: | ||
736 | stdout = None | ||
737 | else: | ||
738 | stdout = subprocess.PIPE | ||
739 | logger.debug("Running command %s" % cmd_desc) | ||
740 | if extra_env or remove_from_env: | ||
741 | env = os.environ.copy() | ||
742 | if extra_env: | ||
743 | env.update(extra_env) | ||
744 | if remove_from_env: | ||
745 | for varname in remove_from_env: | ||
746 | env.pop(varname, None) | ||
747 | else: | ||
748 | env = None | ||
749 | try: | ||
750 | proc = subprocess.Popen( | ||
751 | cmd, stderr=subprocess.STDOUT, | ||
752 | stdin=None if stdin is None else subprocess.PIPE, | ||
753 | stdout=stdout, | ||
754 | cwd=cwd, env=env) | ||
755 | except Exception: | ||
756 | e = sys.exc_info()[1] | ||
757 | logger.fatal( | ||
758 | "Error %s while executing command %s" % (e, cmd_desc)) | ||
759 | raise | ||
760 | all_output = [] | ||
761 | if stdout is not None: | ||
762 | if stdin is not None: | ||
763 | proc.stdin.write(stdin) | ||
764 | proc.stdin.close() | ||
765 | |||
766 | stdout = proc.stdout | ||
767 | encoding = sys.getdefaultencoding() | ||
768 | fs_encoding = sys.getfilesystemencoding() | ||
769 | while 1: | ||
770 | line = stdout.readline() | ||
771 | try: | ||
772 | line = line.decode(encoding) | ||
773 | except UnicodeDecodeError: | ||
774 | line = line.decode(fs_encoding) | ||
775 | if not line: | ||
776 | break | ||
777 | line = line.rstrip() | ||
778 | all_output.append(line) | ||
779 | if filter_stdout: | ||
780 | level = filter_stdout(line) | ||
781 | if isinstance(level, tuple): | ||
782 | level, line = level | ||
783 | logger.log(level, line) | ||
784 | if not logger.stdout_level_matches(level): | ||
785 | logger.show_progress() | ||
786 | else: | ||
787 | logger.info(line) | ||
788 | else: | ||
789 | proc.communicate(stdin) | ||
790 | proc.wait() | ||
791 | if proc.returncode: | ||
792 | if raise_on_returncode: | ||
793 | if all_output: | ||
794 | logger.notify('Complete output from command %s:' % cmd_desc) | ||
795 | logger.notify('\n'.join(all_output) + '\n----------------------------------------') | ||
796 | raise OSError( | ||
797 | "Command %s failed with error code %s" | ||
798 | % (cmd_desc, proc.returncode)) | ||
799 | else: | ||
800 | logger.warn( | ||
801 | "Command %s had error code %s" | ||
802 | % (cmd_desc, proc.returncode)) | ||
803 | |||
804 | def filter_install_output(line): | ||
805 | if line.strip().startswith('running'): | ||
806 | return Logger.INFO | ||
807 | return Logger.DEBUG | ||
808 | |||
809 | def find_wheels(projects, search_dirs): | ||
810 | """Find wheels from which we can import PROJECTS. | ||
811 | |||
812 | Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return | ||
813 | a list of the first wheel found for each PROJECT | ||
814 | """ | ||
815 | |||
816 | wheels = [] | ||
817 | |||
818 | # Look through SEARCH_DIRS for the first suitable wheel. Don't bother | ||
819 | # about version checking here, as this is simply to get something we can | ||
820 | # then use to install the correct version. | ||
821 | for project in projects: | ||
822 | for dirname in search_dirs: | ||
823 | # This relies on only having "universal" wheels available. | ||
824 | # The pattern could be tightened to require -py2.py3-none-any.whl. | ||
825 | files = glob.glob(os.path.join(dirname, project + '-*.whl')) | ||
826 | if files: | ||
827 | wheels.append(os.path.abspath(files[0])) | ||
828 | break | ||
829 | else: | ||
830 | # We're out of luck, so quit with a suitable error | ||
831 | logger.fatal('Cannot find a wheel for %s' % (project,)) | ||
832 | |||
833 | return wheels | ||
834 | |||
835 | def install_wheel(project_names, py_executable, search_dirs=None, | ||
836 | download=False): | ||
837 | if search_dirs is None: | ||
838 | search_dirs = file_search_dirs() | ||
839 | |||
840 | wheels = find_wheels(['setuptools', 'pip'], search_dirs) | ||
841 | pythonpath = os.pathsep.join(wheels) | ||
842 | |||
843 | # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths | ||
844 | # with spaces in them. Convert any of those to local file:// URL form. | ||
845 | try: | ||
846 | from urlparse import urljoin | ||
847 | from urllib import pathname2url | ||
848 | except ImportError: | ||
849 | from urllib.parse import urljoin | ||
850 | from urllib.request import pathname2url | ||
851 | def space_path2url(p): | ||
852 | if ' ' not in p: | ||
853 | return p | ||
854 | return urljoin('file:', pathname2url(os.path.abspath(p))) | ||
855 | findlinks = ' '.join(space_path2url(d) for d in search_dirs) | ||
856 | |||
857 | SCRIPT = textwrap.dedent(""" | ||
858 | import sys | ||
859 | import pkgutil | ||
860 | import tempfile | ||
861 | import os | ||
862 | |||
863 | import pip | ||
864 | |||
865 | cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem") | ||
866 | if cert_data is not None: | ||
867 | cert_file = tempfile.NamedTemporaryFile(delete=False) | ||
868 | cert_file.write(cert_data) | ||
869 | cert_file.close() | ||
870 | else: | ||
871 | cert_file = None | ||
872 | |||
873 | try: | ||
874 | args = ["install", "--ignore-installed"] | ||
875 | if cert_file is not None: | ||
876 | args += ["--cert", cert_file.name] | ||
877 | args += sys.argv[1:] | ||
878 | |||
879 | sys.exit(pip.main(args)) | ||
880 | finally: | ||
881 | if cert_file is not None: | ||
882 | os.remove(cert_file.name) | ||
883 | """).encode("utf8") | ||
884 | |||
885 | cmd = [py_executable, '-'] + project_names | ||
886 | logger.start_progress('Installing %s...' % (', '.join(project_names))) | ||
887 | logger.indent += 2 | ||
888 | |||
889 | env = { | ||
890 | "PYTHONPATH": pythonpath, | ||
891 | "JYTHONPATH": pythonpath, # for Jython < 3.x | ||
892 | "PIP_FIND_LINKS": findlinks, | ||
893 | "PIP_USE_WHEEL": "1", | ||
894 | "PIP_ONLY_BINARY": ":all:", | ||
895 | "PIP_PRE": "1", | ||
896 | "PIP_USER": "0", | ||
897 | } | ||
898 | |||
899 | if not download: | ||
900 | env["PIP_NO_INDEX"] = "1" | ||
901 | |||
902 | try: | ||
903 | call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT) | ||
904 | finally: | ||
905 | logger.indent -= 2 | ||
906 | logger.end_progress() | ||
907 | |||
908 | |||
909 | def create_environment(home_dir, site_packages=False, clear=False, | ||
910 | unzip_setuptools=False, | ||
911 | prompt=None, search_dirs=None, download=False, | ||
912 | no_setuptools=False, no_pip=False, no_wheel=False, | ||
913 | symlink=True): | ||
914 | """ | ||
915 | Creates a new environment in ``home_dir``. | ||
916 | |||
917 | If ``site_packages`` is true, then the global ``site-packages/`` | ||
918 | directory will be on the path. | ||
919 | |||
920 | If ``clear`` is true (default False) then the environment will | ||
921 | first be cleared. | ||
922 | """ | ||
923 | home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | ||
924 | |||
925 | py_executable = os.path.abspath(install_python( | ||
926 | home_dir, lib_dir, inc_dir, bin_dir, | ||
927 | site_packages=site_packages, clear=clear, symlink=symlink)) | ||
928 | |||
929 | install_distutils(home_dir) | ||
930 | |||
931 | to_install = [] | ||
932 | |||
933 | if not no_setuptools: | ||
934 | to_install.append('setuptools') | ||
935 | |||
936 | if not no_pip: | ||
937 | to_install.append('pip') | ||
938 | |||
939 | if not no_wheel: | ||
940 | to_install.append('wheel') | ||
941 | |||
942 | if to_install: | ||
943 | install_wheel( | ||
944 | to_install, | ||
945 | py_executable, | ||
946 | search_dirs, | ||
947 | download=download, | ||
948 | ) | ||
949 | |||
950 | install_activate(home_dir, bin_dir, prompt) | ||
951 | |||
952 | install_python_config(home_dir, bin_dir, prompt) | ||
953 | |||
954 | def is_executable_file(fpath): | ||
955 | return os.path.isfile(fpath) and os.access(fpath, os.X_OK) | ||
956 | |||
957 | def path_locations(home_dir): | ||
958 | """Return the path locations for the environment (where libraries are, | ||
959 | where scripts go, etc)""" | ||
960 | home_dir = os.path.abspath(home_dir) | ||
961 | # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its | ||
962 | # prefix arg is broken: http://bugs.python.org/issue3386 | ||
963 | if is_win: | ||
964 | # Windows has lots of problems with executables with spaces in | ||
965 | # the name; this function will remove them (using the ~1 | ||
966 | # format): | ||
967 | mkdir(home_dir) | ||
968 | if ' ' in home_dir: | ||
969 | import ctypes | ||
970 | GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW | ||
971 | size = max(len(home_dir)+1, 256) | ||
972 | buf = ctypes.create_unicode_buffer(size) | ||
973 | try: | ||
974 | u = unicode | ||
975 | except NameError: | ||
976 | u = str | ||
977 | ret = GetShortPathName(u(home_dir), buf, size) | ||
978 | if not ret: | ||
979 | print('Error: the path "%s" has a space in it' % home_dir) | ||
980 | print('We could not determine the short pathname for it.') | ||
981 | print('Exiting.') | ||
982 | sys.exit(3) | ||
983 | home_dir = str(buf.value) | ||
984 | lib_dir = join(home_dir, 'Lib') | ||
985 | inc_dir = join(home_dir, 'Include') | ||
986 | bin_dir = join(home_dir, 'Scripts') | ||
987 | if is_jython: | ||
988 | lib_dir = join(home_dir, 'Lib') | ||
989 | inc_dir = join(home_dir, 'Include') | ||
990 | bin_dir = join(home_dir, 'bin') | ||
991 | elif is_pypy: | ||
992 | lib_dir = home_dir | ||
993 | inc_dir = join(home_dir, 'include') | ||
994 | bin_dir = join(home_dir, 'bin') | ||
995 | elif not is_win: | ||
996 | lib_dir = join(home_dir, 'lib', py_version) | ||
997 | inc_dir = join(home_dir, 'include', py_version + abiflags) | ||
998 | bin_dir = join(home_dir, 'bin') | ||
999 | return home_dir, lib_dir, inc_dir, bin_dir | ||
1000 | |||
1001 | |||
1002 | def change_prefix(filename, dst_prefix): | ||
1003 | prefixes = [sys.prefix] | ||
1004 | |||
1005 | if is_darwin: | ||
1006 | prefixes.extend(( | ||
1007 | os.path.join("/Library/Python", sys.version[:3], "site-packages"), | ||
1008 | os.path.join(sys.prefix, "Extras", "lib", "python"), | ||
1009 | os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"), | ||
1010 | # Python 2.6 no-frameworks | ||
1011 | os.path.join("~", ".local", "lib","python", sys.version[:3], "site-packages"), | ||
1012 | # System Python 2.7 on OSX Mountain Lion | ||
1013 | os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"))) | ||
1014 | |||
1015 | if hasattr(sys, 'real_prefix'): | ||
1016 | prefixes.append(sys.real_prefix) | ||
1017 | if hasattr(sys, 'base_prefix'): | ||
1018 | prefixes.append(sys.base_prefix) | ||
1019 | prefixes = list(map(os.path.expanduser, prefixes)) | ||
1020 | prefixes = list(map(os.path.abspath, prefixes)) | ||
1021 | # Check longer prefixes first so we don't split in the middle of a filename | ||
1022 | prefixes = sorted(prefixes, key=len, reverse=True) | ||
1023 | filename = os.path.abspath(filename) | ||
1024 | # On Windows, make sure drive letter is uppercase | ||
1025 | if is_win and filename[0] in 'abcdefghijklmnopqrstuvwxyz': | ||
1026 | filename = filename[0].upper() + filename[1:] | ||
1027 | for i, prefix in enumerate(prefixes): | ||
1028 | if is_win and prefix[0] in 'abcdefghijklmnopqrstuvwxyz': | ||
1029 | prefixes[i] = prefix[0].upper() + prefix[1:] | ||
1030 | for src_prefix in prefixes: | ||
1031 | if filename.startswith(src_prefix): | ||
1032 | _, relpath = filename.split(src_prefix, 1) | ||
1033 | if src_prefix != os.sep: # sys.prefix == "/" | ||
1034 | assert relpath[0] == os.sep | ||
1035 | relpath = relpath[1:] | ||
1036 | return join(dst_prefix, relpath) | ||
1037 | assert False, "Filename %s does not start with any of these prefixes: %s" % \ | ||
1038 | (filename, prefixes) | ||
1039 | |||
1040 | def copy_required_modules(dst_prefix, symlink): | ||
1041 | import imp | ||
1042 | |||
1043 | for modname in REQUIRED_MODULES: | ||
1044 | if modname in sys.builtin_module_names: | ||
1045 | logger.info("Ignoring built-in bootstrap module: %s" % modname) | ||
1046 | continue | ||
1047 | try: | ||
1048 | f, filename, _ = imp.find_module(modname) | ||
1049 | except ImportError: | ||
1050 | logger.info("Cannot import bootstrap module: %s" % modname) | ||
1051 | else: | ||
1052 | if f is not None: | ||
1053 | f.close() | ||
1054 | # special-case custom readline.so on OS X, but not for pypy: | ||
1055 | if modname == 'readline' and sys.platform == 'darwin' and not ( | ||
1056 | is_pypy or filename.endswith(join('lib-dynload', 'readline.so'))): | ||
1057 | dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[:3], 'readline.so') | ||
1058 | elif modname == 'readline' and sys.platform == 'win32': | ||
1059 | # special-case for Windows, where readline is not a | ||
1060 | # standard module, though it may have been installed in | ||
1061 | # site-packages by a third-party package | ||
1062 | pass | ||
1063 | else: | ||
1064 | dst_filename = change_prefix(filename, dst_prefix) | ||
1065 | copyfile(filename, dst_filename, symlink) | ||
1066 | if filename.endswith('.pyc'): | ||
1067 | pyfile = filename[:-1] | ||
1068 | if os.path.exists(pyfile): | ||
1069 | copyfile(pyfile, dst_filename[:-1], symlink) | ||
1070 | |||
1071 | def copy_tcltk(src, dest, symlink): | ||
1072 | """ copy tcl/tk libraries on Windows (issue #93) """ | ||
1073 | if majver == 2: | ||
1074 | libver = '8.5' | ||
1075 | else: | ||
1076 | libver = '8.6' | ||
1077 | for name in ['tcl', 'tk']: | ||
1078 | srcdir = src + '/tcl/' + name + libver | ||
1079 | dstdir = dest + '/tcl/' + name + libver | ||
1080 | copyfileordir(srcdir, dstdir, symlink) | ||
1081 | |||
1082 | def subst_path(prefix_path, prefix, home_dir): | ||
1083 | prefix_path = os.path.normpath(prefix_path) | ||
1084 | prefix = os.path.normpath(prefix) | ||
1085 | home_dir = os.path.normpath(home_dir) | ||
1086 | if not prefix_path.startswith(prefix): | ||
1087 | logger.warn('Path not in prefix %r %r', prefix_path, prefix) | ||
1088 | return | ||
1089 | return prefix_path.replace(prefix, home_dir, 1) | ||
1090 | |||
1091 | |||
1092 | def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True): | ||
1093 | """Install just the base environment, no distutils patches etc""" | ||
1094 | if sys.executable.startswith(bin_dir): | ||
1095 | print('Please use the *system* python to run this script') | ||
1096 | return | ||
1097 | |||
1098 | if clear: | ||
1099 | rmtree(lib_dir) | ||
1100 | ## FIXME: why not delete it? | ||
1101 | ## Maybe it should delete everything with #!/path/to/venv/python in it | ||
1102 | logger.notify('Not deleting %s', bin_dir) | ||
1103 | |||
1104 | if hasattr(sys, 'real_prefix'): | ||
1105 | logger.notify('Using real prefix %r' % sys.real_prefix) | ||
1106 | prefix = sys.real_prefix | ||
1107 | elif hasattr(sys, 'base_prefix'): | ||
1108 | logger.notify('Using base prefix %r' % sys.base_prefix) | ||
1109 | prefix = sys.base_prefix | ||
1110 | else: | ||
1111 | prefix = sys.prefix | ||
1112 | mkdir(lib_dir) | ||
1113 | fix_lib64(lib_dir, symlink) | ||
1114 | stdlib_dirs = [os.path.dirname(os.__file__)] | ||
1115 | if is_win: | ||
1116 | stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs')) | ||
1117 | elif is_darwin: | ||
1118 | stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages')) | ||
1119 | if hasattr(os, 'symlink'): | ||
1120 | logger.info('Symlinking Python bootstrap modules') | ||
1121 | else: | ||
1122 | logger.info('Copying Python bootstrap modules') | ||
1123 | logger.indent += 2 | ||
1124 | try: | ||
1125 | # copy required files... | ||
1126 | for stdlib_dir in stdlib_dirs: | ||
1127 | if not os.path.isdir(stdlib_dir): | ||
1128 | continue | ||
1129 | for fn in os.listdir(stdlib_dir): | ||
1130 | bn = os.path.splitext(fn)[0] | ||
1131 | if fn != 'site-packages' and bn in REQUIRED_FILES: | ||
1132 | copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink) | ||
1133 | # ...and modules | ||
1134 | copy_required_modules(home_dir, symlink) | ||
1135 | finally: | ||
1136 | logger.indent -= 2 | ||
1137 | # ...copy tcl/tk | ||
1138 | if is_win: | ||
1139 | copy_tcltk(prefix, home_dir, symlink) | ||
1140 | mkdir(join(lib_dir, 'site-packages')) | ||
1141 | import site | ||
1142 | site_filename = site.__file__ | ||
1143 | if site_filename.endswith('.pyc') or site_filename.endswith('.pyo'): | ||
1144 | site_filename = site_filename[:-1] | ||
1145 | elif site_filename.endswith('$py.class'): | ||
1146 | site_filename = site_filename.replace('$py.class', '.py') | ||
1147 | site_filename_dst = change_prefix(site_filename, home_dir) | ||
1148 | site_dir = os.path.dirname(site_filename_dst) | ||
1149 | writefile(site_filename_dst, SITE_PY) | ||
1150 | writefile(join(site_dir, 'orig-prefix.txt'), prefix) | ||
1151 | site_packages_filename = join(site_dir, 'no-global-site-packages.txt') | ||
1152 | if not site_packages: | ||
1153 | writefile(site_packages_filename, '') | ||
1154 | |||
1155 | if is_pypy or is_win: | ||
1156 | stdinc_dir = join(prefix, 'include') | ||
1157 | else: | ||
1158 | stdinc_dir = join(prefix, 'include', py_version + abiflags) | ||
1159 | if os.path.exists(stdinc_dir): | ||
1160 | copyfile(stdinc_dir, inc_dir, symlink) | ||
1161 | else: | ||
1162 | logger.debug('No include dir %s' % stdinc_dir) | ||
1163 | |||
1164 | platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1) | ||
1165 | if platinc_dir != stdinc_dir: | ||
1166 | platinc_dest = distutils.sysconfig.get_python_inc( | ||
1167 | plat_specific=1, prefix=home_dir) | ||
1168 | if platinc_dir == platinc_dest: | ||
1169 | # Do platinc_dest manually due to a CPython bug; | ||
1170 | # not http://bugs.python.org/issue3386 but a close cousin | ||
1171 | platinc_dest = subst_path(platinc_dir, prefix, home_dir) | ||
1172 | if platinc_dest: | ||
1173 | # PyPy's stdinc_dir and prefix are relative to the original binary | ||
1174 | # (traversing virtualenvs), whereas the platinc_dir is relative to | ||
1175 | # the inner virtualenv and ignores the prefix argument. | ||
1176 | # This seems more evolved than designed. | ||
1177 | copyfile(platinc_dir, platinc_dest, symlink) | ||
1178 | |||
1179 | # pypy never uses exec_prefix, just ignore it | ||
1180 | if sys.exec_prefix != prefix and not is_pypy: | ||
1181 | if is_win: | ||
1182 | exec_dir = join(sys.exec_prefix, 'lib') | ||
1183 | elif is_jython: | ||
1184 | exec_dir = join(sys.exec_prefix, 'Lib') | ||
1185 | else: | ||
1186 | exec_dir = join(sys.exec_prefix, 'lib', py_version) | ||
1187 | for fn in os.listdir(exec_dir): | ||
1188 | copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink) | ||
1189 | |||
1190 | if is_jython: | ||
1191 | # Jython has either jython-dev.jar and javalib/ dir, or just | ||
1192 | # jython.jar | ||
1193 | for name in 'jython-dev.jar', 'javalib', 'jython.jar': | ||
1194 | src = join(prefix, name) | ||
1195 | if os.path.exists(src): | ||
1196 | copyfile(src, join(home_dir, name), symlink) | ||
1197 | # XXX: registry should always exist after Jython 2.5rc1 | ||
1198 | src = join(prefix, 'registry') | ||
1199 | if os.path.exists(src): | ||
1200 | copyfile(src, join(home_dir, 'registry'), symlink=False) | ||
1201 | copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'), | ||
1202 | symlink=False) | ||
1203 | |||
1204 | mkdir(bin_dir) | ||
1205 | py_executable = join(bin_dir, os.path.basename(sys.executable)) | ||
1206 | if 'Python.framework' in prefix: | ||
1207 | # OS X framework builds cause validation to break | ||
1208 | # https://github.com/pypa/virtualenv/issues/322 | ||
1209 | if os.environ.get('__PYVENV_LAUNCHER__'): | ||
1210 | del os.environ["__PYVENV_LAUNCHER__"] | ||
1211 | if re.search(r'/Python(?:-32|-64)*$', py_executable): | ||
1212 | # The name of the python executable is not quite what | ||
1213 | # we want, rename it. | ||
1214 | py_executable = os.path.join( | ||
1215 | os.path.dirname(py_executable), 'python') | ||
1216 | |||
1217 | logger.notify('New %s executable in %s', expected_exe, py_executable) | ||
1218 | pcbuild_dir = os.path.dirname(sys.executable) | ||
1219 | pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pth') | ||
1220 | if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')): | ||
1221 | logger.notify('Detected python running from build directory %s', pcbuild_dir) | ||
1222 | logger.notify('Writing .pth file linking to build directory for *.pyd files') | ||
1223 | writefile(pyd_pth, pcbuild_dir) | ||
1224 | else: | ||
1225 | pcbuild_dir = None | ||
1226 | if os.path.exists(pyd_pth): | ||
1227 | logger.info('Deleting %s (not Windows env or not build directory python)' % pyd_pth) | ||
1228 | os.unlink(pyd_pth) | ||
1229 | |||
1230 | if sys.executable != py_executable: | ||
1231 | ## FIXME: could I just hard link? | ||
1232 | executable = sys.executable | ||
1233 | shutil.copyfile(executable, py_executable) | ||
1234 | make_exe(py_executable) | ||
1235 | if is_win or is_cygwin: | ||
1236 | pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe') | ||
1237 | if os.path.exists(pythonw): | ||
1238 | logger.info('Also created pythonw.exe') | ||
1239 | shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), 'pythonw.exe')) | ||
1240 | python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.exe') | ||
1241 | python_d_dest = os.path.join(os.path.dirname(py_executable), 'python_d.exe') | ||
1242 | if os.path.exists(python_d): | ||
1243 | logger.info('Also created python_d.exe') | ||
1244 | shutil.copyfile(python_d, python_d_dest) | ||
1245 | elif os.path.exists(python_d_dest): | ||
1246 | logger.info('Removed python_d.exe as it is no longer at the source') | ||
1247 | os.unlink(python_d_dest) | ||
1248 | # we need to copy the DLL to enforce that windows will load the correct one. | ||
1249 | # may not exist if we are cygwin. | ||
1250 | py_executable_dll = 'python%s%s.dll' % ( | ||
1251 | sys.version_info[0], sys.version_info[1]) | ||
1252 | py_executable_dll_d = 'python%s%s_d.dll' % ( | ||
1253 | sys.version_info[0], sys.version_info[1]) | ||
1254 | pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll) | ||
1255 | pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d) | ||
1256 | pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d) | ||
1257 | if os.path.exists(pythondll): | ||
1258 | logger.info('Also created %s' % py_executable_dll) | ||
1259 | shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll)) | ||
1260 | if os.path.exists(pythondll_d): | ||
1261 | logger.info('Also created %s' % py_executable_dll_d) | ||
1262 | shutil.copyfile(pythondll_d, pythondll_d_dest) | ||
1263 | elif os.path.exists(pythondll_d_dest): | ||
1264 | logger.info('Removed %s as the source does not exist' % pythondll_d_dest) | ||
1265 | os.unlink(pythondll_d_dest) | ||
1266 | if is_pypy: | ||
1267 | # make a symlink python --> pypy-c | ||
1268 | python_executable = os.path.join(os.path.dirname(py_executable), 'python') | ||
1269 | if sys.platform in ('win32', 'cygwin'): | ||
1270 | python_executable += '.exe' | ||
1271 | logger.info('Also created executable %s' % python_executable) | ||
1272 | copyfile(py_executable, python_executable, symlink) | ||
1273 | |||
1274 | if is_win: | ||
1275 | for name in ['libexpat.dll', 'libpypy.dll', 'libpypy-c.dll', | ||
1276 | 'libeay32.dll', 'ssleay32.dll', 'sqlite3.dll', | ||
1277 | 'tcl85.dll', 'tk85.dll']: | ||
1278 | src = join(prefix, name) | ||
1279 | if os.path.exists(src): | ||
1280 | copyfile(src, join(bin_dir, name), symlink) | ||
1281 | |||
1282 | for d in sys.path: | ||
1283 | if d.endswith('lib_pypy'): | ||
1284 | break | ||
1285 | else: | ||
1286 | logger.fatal('Could not find lib_pypy in sys.path') | ||
1287 | raise SystemExit(3) | ||
1288 | logger.info('Copying lib_pypy') | ||
1289 | copyfile(d, os.path.join(home_dir, 'lib_pypy'), symlink) | ||
1290 | |||
1291 | if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe: | ||
1292 | secondary_exe = os.path.join(os.path.dirname(py_executable), | ||
1293 | expected_exe) | ||
1294 | py_executable_ext = os.path.splitext(py_executable)[1] | ||
1295 | if py_executable_ext.lower() == '.exe': | ||
1296 | # python2.4 gives an extension of '.4' :P | ||
1297 | secondary_exe += py_executable_ext | ||
1298 | if os.path.exists(secondary_exe): | ||
1299 | logger.warn('Not overwriting existing %s script %s (you must use %s)' | ||
1300 | % (expected_exe, secondary_exe, py_executable)) | ||
1301 | else: | ||
1302 | logger.notify('Also creating executable in %s' % secondary_exe) | ||
1303 | shutil.copyfile(sys.executable, secondary_exe) | ||
1304 | make_exe(secondary_exe) | ||
1305 | |||
1306 | if '.framework' in prefix: | ||
1307 | if 'Python.framework' in prefix: | ||
1308 | logger.debug('MacOSX Python framework detected') | ||
1309 | # Make sure we use the embedded interpreter inside | ||
1310 | # the framework, even if sys.executable points to | ||
1311 | # the stub executable in ${sys.prefix}/bin | ||
1312 | # See http://groups.google.com/group/python-virtualenv/ | ||
1313 | # browse_thread/thread/17cab2f85da75951 | ||
1314 | original_python = os.path.join( | ||
1315 | prefix, 'Resources/Python.app/Contents/MacOS/Python') | ||
1316 | if 'EPD' in prefix: | ||
1317 | logger.debug('EPD framework detected') | ||
1318 | original_python = os.path.join(prefix, 'bin/python') | ||
1319 | shutil.copy(original_python, py_executable) | ||
1320 | |||
1321 | # Copy the framework's dylib into the virtual | ||
1322 | # environment | ||
1323 | virtual_lib = os.path.join(home_dir, '.Python') | ||
1324 | |||
1325 | if os.path.exists(virtual_lib): | ||
1326 | os.unlink(virtual_lib) | ||
1327 | copyfile( | ||
1328 | os.path.join(prefix, 'Python'), | ||
1329 | virtual_lib, | ||
1330 | symlink) | ||
1331 | |||
1332 | # And then change the install_name of the copied python executable | ||
1333 | try: | ||
1334 | mach_o_change(py_executable, | ||
1335 | os.path.join(prefix, 'Python'), | ||
1336 | '@executable_path/../.Python') | ||
1337 | except: | ||
1338 | e = sys.exc_info()[1] | ||
1339 | logger.warn("Could not call mach_o_change: %s. " | ||
1340 | "Trying to call install_name_tool instead." % e) | ||
1341 | try: | ||
1342 | call_subprocess( | ||
1343 | ["install_name_tool", "-change", | ||
1344 | os.path.join(prefix, 'Python'), | ||
1345 | '@executable_path/../.Python', | ||
1346 | py_executable]) | ||
1347 | except: | ||
1348 | logger.fatal("Could not call install_name_tool -- you must " | ||
1349 | "have Apple's development tools installed") | ||
1350 | raise | ||
1351 | |||
1352 | if not is_win: | ||
1353 | # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist | ||
1354 | py_exe_version_major = 'python%s' % sys.version_info[0] | ||
1355 | py_exe_version_major_minor = 'python%s.%s' % ( | ||
1356 | sys.version_info[0], sys.version_info[1]) | ||
1357 | py_exe_no_version = 'python' | ||
1358 | required_symlinks = [ py_exe_no_version, py_exe_version_major, | ||
1359 | py_exe_version_major_minor ] | ||
1360 | |||
1361 | py_executable_base = os.path.basename(py_executable) | ||
1362 | |||
1363 | if py_executable_base in required_symlinks: | ||
1364 | # Don't try to symlink to yourself. | ||
1365 | required_symlinks.remove(py_executable_base) | ||
1366 | |||
1367 | for pth in required_symlinks: | ||
1368 | full_pth = join(bin_dir, pth) | ||
1369 | if os.path.exists(full_pth): | ||
1370 | os.unlink(full_pth) | ||
1371 | if symlink: | ||
1372 | os.symlink(py_executable_base, full_pth) | ||
1373 | else: | ||
1374 | copyfile(py_executable, full_pth, symlink) | ||
1375 | |||
1376 | if is_win and ' ' in py_executable: | ||
1377 | # There's a bug with subprocess on Windows when using a first | ||
1378 | # argument that has a space in it. Instead we have to quote | ||
1379 | # the value: | ||
1380 | py_executable = '"%s"' % py_executable | ||
1381 | # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks | ||
1382 | cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' | ||
1383 | 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] | ||
1384 | logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) | ||
1385 | try: | ||
1386 | proc = subprocess.Popen(cmd, | ||
1387 | stdout=subprocess.PIPE) | ||
1388 | proc_stdout, proc_stderr = proc.communicate() | ||
1389 | except OSError: | ||
1390 | e = sys.exc_info()[1] | ||
1391 | if e.errno == errno.EACCES: | ||
1392 | logger.fatal('ERROR: The executable %s could not be run: %s' % (py_executable, e)) | ||
1393 | sys.exit(100) | ||
1394 | else: | ||
1395 | raise e | ||
1396 | |||
1397 | proc_stdout = proc_stdout.strip().decode("utf-8") | ||
1398 | proc_stdout = os.path.normcase(os.path.abspath(proc_stdout)) | ||
1399 | norm_home_dir = os.path.normcase(os.path.abspath(home_dir)) | ||
1400 | if hasattr(norm_home_dir, 'decode'): | ||
1401 | norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding()) | ||
1402 | if proc_stdout != norm_home_dir: | ||
1403 | logger.fatal( | ||
1404 | 'ERROR: The executable %s is not functioning' % py_executable) | ||
1405 | logger.fatal( | ||
1406 | 'ERROR: It thinks sys.prefix is %r (should be %r)' | ||
1407 | % (proc_stdout, norm_home_dir)) | ||
1408 | logger.fatal( | ||
1409 | 'ERROR: virtualenv is not compatible with this system or executable') | ||
1410 | if is_win: | ||
1411 | logger.fatal( | ||
1412 | 'Note: some Windows users have reported this error when they ' | ||
1413 | 'installed Python for "Only this user" or have multiple ' | ||
1414 | 'versions of Python installed. Copying the appropriate ' | ||
1415 | 'PythonXX.dll to the virtualenv Scripts/ directory may fix ' | ||
1416 | 'this problem.') | ||
1417 | sys.exit(100) | ||
1418 | else: | ||
1419 | logger.info('Got sys.prefix result: %r' % proc_stdout) | ||
1420 | |||
1421 | pydistutils = os.path.expanduser('~/.pydistutils.cfg') | ||
1422 | if os.path.exists(pydistutils): | ||
1423 | logger.notify('Please make sure you remove any previous custom paths from ' | ||
1424 | 'your %s file.' % pydistutils) | ||
1425 | ## FIXME: really this should be calculated earlier | ||
1426 | |||
1427 | fix_local_scheme(home_dir, symlink) | ||
1428 | |||
1429 | if site_packages: | ||
1430 | if os.path.exists(site_packages_filename): | ||
1431 | logger.info('Deleting %s' % site_packages_filename) | ||
1432 | os.unlink(site_packages_filename) | ||
1433 | |||
1434 | return py_executable | ||
1435 | |||
1436 | |||
1437 | def install_activate(home_dir, bin_dir, prompt=None): | ||
1438 | if is_win or is_jython and os._name == 'nt': | ||
1439 | files = { | ||
1440 | 'activate.bat': ACTIVATE_BAT, | ||
1441 | 'deactivate.bat': DEACTIVATE_BAT, | ||
1442 | 'activate.ps1': ACTIVATE_PS, | ||
1443 | } | ||
1444 | |||
1445 | # MSYS needs paths of the form /c/path/to/file | ||
1446 | drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) | ||
1447 | home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) | ||
1448 | |||
1449 | # Run-time conditional enables (basic) Cygwin compatibility | ||
1450 | home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'; else echo '%s'; fi;)""" % | ||
1451 | (home_dir, home_dir_msys)) | ||
1452 | files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh) | ||
1453 | |||
1454 | else: | ||
1455 | files = {'activate': ACTIVATE_SH} | ||
1456 | |||
1457 | # suppling activate.fish in addition to, not instead of, the | ||
1458 | # bash script support. | ||
1459 | files['activate.fish'] = ACTIVATE_FISH | ||
1460 | |||
1461 | # same for csh/tcsh support... | ||
1462 | files['activate.csh'] = ACTIVATE_CSH | ||
1463 | |||
1464 | files['activate_this.py'] = ACTIVATE_THIS | ||
1465 | |||
1466 | install_files(home_dir, bin_dir, prompt, files) | ||
1467 | |||
1468 | def install_files(home_dir, bin_dir, prompt, files): | ||
1469 | if hasattr(home_dir, 'decode'): | ||
1470 | home_dir = home_dir.decode(sys.getfilesystemencoding()) | ||
1471 | vname = os.path.basename(home_dir) | ||
1472 | for name, content in files.items(): | ||
1473 | content = content.replace('__VIRTUAL_PROMPT__', prompt or '') | ||
1474 | content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vname) | ||
1475 | content = content.replace('__VIRTUAL_ENV__', home_dir) | ||
1476 | content = content.replace('__VIRTUAL_NAME__', vname) | ||
1477 | content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) | ||
1478 | writefile(os.path.join(bin_dir, name), content) | ||
1479 | |||
1480 | def install_python_config(home_dir, bin_dir, prompt=None): | ||
1481 | if sys.platform == 'win32' or is_jython and os._name == 'nt': | ||
1482 | files = {} | ||
1483 | else: | ||
1484 | files = {'python-config': PYTHON_CONFIG} | ||
1485 | install_files(home_dir, bin_dir, prompt, files) | ||
1486 | for name, content in files.items(): | ||
1487 | make_exe(os.path.join(bin_dir, name)) | ||
1488 | |||
1489 | def install_distutils(home_dir): | ||
1490 | distutils_path = change_prefix(distutils.__path__[0], home_dir) | ||
1491 | mkdir(distutils_path) | ||
1492 | ## FIXME: maybe this prefix setting should only be put in place if | ||
1493 | ## there's a local distutils.cfg with a prefix setting? | ||
1494 | home_dir = os.path.abspath(home_dir) | ||
1495 | ## FIXME: this is breaking things, removing for now: | ||
1496 | #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir | ||
1497 | writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) | ||
1498 | writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, overwrite=False) | ||
1499 | |||
1500 | def fix_local_scheme(home_dir, symlink=True): | ||
1501 | """ | ||
1502 | Platforms that use the "posix_local" install scheme (like Ubuntu with | ||
1503 | Python 2.7) need to be given an additional "local" location, sigh. | ||
1504 | """ | ||
1505 | try: | ||
1506 | import sysconfig | ||
1507 | except ImportError: | ||
1508 | pass | ||
1509 | else: | ||
1510 | if sysconfig._get_default_scheme() == 'posix_local': | ||
1511 | local_path = os.path.join(home_dir, 'local') | ||
1512 | if not os.path.exists(local_path): | ||
1513 | os.mkdir(local_path) | ||
1514 | for subdir_name in os.listdir(home_dir): | ||
1515 | if subdir_name == 'local': | ||
1516 | continue | ||
1517 | copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)), \ | ||
1518 | os.path.join(local_path, subdir_name), symlink) | ||
1519 | |||
1520 | def fix_lib64(lib_dir, symlink=True): | ||
1521 | """ | ||
1522 | Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y | ||
1523 | instead of lib/pythonX.Y. If this is such a platform we'll just create a | ||
1524 | symlink so lib64 points to lib | ||
1525 | """ | ||
1526 | # PyPy's library path scheme is not affected by this. | ||
1527 | # Return early or we will die on the following assert. | ||
1528 | if is_pypy: | ||
1529 | logger.debug('PyPy detected, skipping lib64 symlinking') | ||
1530 | return | ||
1531 | # Check we have a lib64 library path | ||
1532 | if not [p for p in distutils.sysconfig.get_config_vars().values() | ||
1533 | if isinstance(p, basestring) and 'lib64' in p]: | ||
1534 | return | ||
1535 | |||
1536 | logger.debug('This system uses lib64; symlinking lib64 to lib') | ||
1537 | |||
1538 | assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( | ||
1539 | "Unexpected python lib dir: %r" % lib_dir) | ||
1540 | lib_parent = os.path.dirname(lib_dir) | ||
1541 | top_level = os.path.dirname(lib_parent) | ||
1542 | lib_dir = os.path.join(top_level, 'lib') | ||
1543 | lib64_link = os.path.join(top_level, 'lib64') | ||
1544 | assert os.path.basename(lib_parent) == 'lib', ( | ||
1545 | "Unexpected parent dir: %r" % lib_parent) | ||
1546 | if os.path.lexists(lib64_link): | ||
1547 | return | ||
1548 | if symlink: | ||
1549 | os.symlink('lib', lib64_link) | ||
1550 | else: | ||
1551 | copyfile('lib', lib64_link) | ||
1552 | |||
1553 | def resolve_interpreter(exe): | ||
1554 | """ | ||
1555 | If the executable given isn't an absolute path, search $PATH for the interpreter | ||
1556 | """ | ||
1557 | # If the "executable" is a version number, get the installed executable for | ||
1558 | # that version | ||
1559 | python_versions = get_installed_pythons() | ||
1560 | if exe in python_versions: | ||
1561 | exe = python_versions[exe] | ||
1562 | |||
1563 | if os.path.abspath(exe) != exe: | ||
1564 | paths = os.environ.get('PATH', '').split(os.pathsep) | ||
1565 | for path in paths: | ||
1566 | if os.path.exists(join(path, exe)): | ||
1567 | exe = join(path, exe) | ||
1568 | break | ||
1569 | if not os.path.exists(exe): | ||
1570 | logger.fatal('The executable %s (from --python=%s) does not exist' % (exe, exe)) | ||
1571 | raise SystemExit(3) | ||
1572 | if not is_executable(exe): | ||
1573 | logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe)) | ||
1574 | raise SystemExit(3) | ||
1575 | return exe | ||
1576 | |||
1577 | def is_executable(exe): | ||
1578 | """Checks a file is executable""" | ||
1579 | return os.access(exe, os.X_OK) | ||
1580 | |||
1581 | ############################################################ | ||
1582 | ## Relocating the environment: | ||
1583 | |||
1584 | def make_environment_relocatable(home_dir): | ||
1585 | """ | ||
1586 | Makes the already-existing environment use relative paths, and takes out | ||
1587 | the #!-based environment selection in scripts. | ||
1588 | """ | ||
1589 | home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | ||
1590 | activate_this = os.path.join(bin_dir, 'activate_this.py') | ||
1591 | if not os.path.exists(activate_this): | ||
1592 | logger.fatal( | ||
1593 | 'The environment doesn\'t have a file %s -- please re-run virtualenv ' | ||
1594 | 'on this environment to update it' % activate_this) | ||
1595 | fixup_scripts(home_dir, bin_dir) | ||
1596 | fixup_pth_and_egg_link(home_dir) | ||
1597 | ## FIXME: need to fix up distutils.cfg | ||
1598 | |||
1599 | OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3], | ||
1600 | 'activate', 'activate.bat', 'activate_this.py', | ||
1601 | 'activate.fish', 'activate.csh'] | ||
1602 | |||
1603 | def fixup_scripts(home_dir, bin_dir): | ||
1604 | if is_win: | ||
1605 | new_shebang_args = ( | ||
1606 | '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')), | ||
1607 | '', '.exe') | ||
1608 | else: | ||
1609 | new_shebang_args = ('/usr/bin/env', sys.version[:3], '') | ||
1610 | |||
1611 | # This is what we expect at the top of scripts: | ||
1612 | shebang = '#!%s' % os.path.normcase(os.path.join( | ||
1613 | os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2])) | ||
1614 | # This is what we'll put: | ||
1615 | new_shebang = '#!%s python%s%s' % new_shebang_args | ||
1616 | |||
1617 | for filename in os.listdir(bin_dir): | ||
1618 | filename = os.path.join(bin_dir, filename) | ||
1619 | if not os.path.isfile(filename): | ||
1620 | # ignore subdirs, e.g. .svn ones. | ||
1621 | continue | ||
1622 | lines = None | ||
1623 | with open(filename, 'rb') as f: | ||
1624 | try: | ||
1625 | lines = f.read().decode('utf-8').splitlines() | ||
1626 | except UnicodeDecodeError: | ||
1627 | # This is probably a binary program instead | ||
1628 | # of a script, so just ignore it. | ||
1629 | continue | ||
1630 | if not lines: | ||
1631 | logger.warn('Script %s is an empty file' % filename) | ||
1632 | continue | ||
1633 | |||
1634 | old_shebang = lines[0].strip() | ||
1635 | old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) | ||
1636 | |||
1637 | if not old_shebang.startswith(shebang): | ||
1638 | if os.path.basename(filename) in OK_ABS_SCRIPTS: | ||
1639 | logger.debug('Cannot make script %s relative' % filename) | ||
1640 | elif lines[0].strip() == new_shebang: | ||
1641 | logger.info('Script %s has already been made relative' % filename) | ||
1642 | else: | ||
1643 | logger.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)' | ||
1644 | % (filename, shebang)) | ||
1645 | continue | ||
1646 | logger.notify('Making script %s relative' % filename) | ||
1647 | script = relative_script([new_shebang] + lines[1:]) | ||
1648 | with open(filename, 'wb') as f: | ||
1649 | f.write('\n'.join(script).encode('utf-8')) | ||
1650 | |||
1651 | |||
1652 | def relative_script(lines): | ||
1653 | "Return a script that'll work in a relocatable environment." | ||
1654 | activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(), activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this" | ||
1655 | # Find the last future statement in the script. If we insert the activation | ||
1656 | # line before a future statement, Python will raise a SyntaxError. | ||
1657 | activate_at = None | ||
1658 | for idx, line in reversed(list(enumerate(lines))): | ||
1659 | if line.split()[:3] == ['from', '__future__', 'import']: | ||
1660 | activate_at = idx + 1 | ||
1661 | break | ||
1662 | if activate_at is None: | ||
1663 | # Activate after the shebang. | ||
1664 | activate_at = 1 | ||
1665 | return lines[:activate_at] + ['', activate, ''] + lines[activate_at:] | ||
1666 | |||
1667 | def fixup_pth_and_egg_link(home_dir, sys_path=None): | ||
1668 | """Makes .pth and .egg-link files use relative paths""" | ||
1669 | home_dir = os.path.normcase(os.path.abspath(home_dir)) | ||
1670 | if sys_path is None: | ||
1671 | sys_path = sys.path | ||
1672 | for path in sys_path: | ||
1673 | if not path: | ||
1674 | path = '.' | ||
1675 | if not os.path.isdir(path): | ||
1676 | continue | ||
1677 | path = os.path.normcase(os.path.abspath(path)) | ||
1678 | if not path.startswith(home_dir): | ||
1679 | logger.debug('Skipping system (non-environment) directory %s' % path) | ||
1680 | continue | ||
1681 | for filename in os.listdir(path): | ||
1682 | filename = os.path.join(path, filename) | ||
1683 | if filename.endswith('.pth'): | ||
1684 | if not os.access(filename, os.W_OK): | ||
1685 | logger.warn('Cannot write .pth file %s, skipping' % filename) | ||
1686 | else: | ||
1687 | fixup_pth_file(filename) | ||
1688 | if filename.endswith('.egg-link'): | ||
1689 | if not os.access(filename, os.W_OK): | ||
1690 | logger.warn('Cannot write .egg-link file %s, skipping' % filename) | ||
1691 | else: | ||
1692 | fixup_egg_link(filename) | ||
1693 | |||
1694 | def fixup_pth_file(filename): | ||
1695 | lines = [] | ||
1696 | prev_lines = [] | ||
1697 | with open(filename) as f: | ||
1698 | prev_lines = f.readlines() | ||
1699 | for line in prev_lines: | ||
1700 | line = line.strip() | ||
1701 | if (not line or line.startswith('#') or line.startswith('import ') | ||
1702 | or os.path.abspath(line) != line): | ||
1703 | lines.append(line) | ||
1704 | else: | ||
1705 | new_value = make_relative_path(filename, line) | ||
1706 | if line != new_value: | ||
1707 | logger.debug('Rewriting path %s as %s (in %s)' % (line, new_value, filename)) | ||
1708 | lines.append(new_value) | ||
1709 | if lines == prev_lines: | ||
1710 | logger.info('No changes to .pth file %s' % filename) | ||
1711 | return | ||
1712 | logger.notify('Making paths in .pth file %s relative' % filename) | ||
1713 | with open(filename, 'w') as f: | ||
1714 | f.write('\n'.join(lines) + '\n') | ||
1715 | |||
1716 | def fixup_egg_link(filename): | ||
1717 | with open(filename) as f: | ||
1718 | link = f.readline().strip() | ||
1719 | if os.path.abspath(link) != link: | ||
1720 | logger.debug('Link in %s already relative' % filename) | ||
1721 | return | ||
1722 | new_link = make_relative_path(filename, link) | ||
1723 | logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) | ||
1724 | with open(filename, 'w') as f: | ||
1725 | f.write(new_link) | ||
1726 | |||
1727 | def make_relative_path(source, dest, dest_is_directory=True): | ||
1728 | """ | ||
1729 | Make a filename relative, where the filename is dest, and it is | ||
1730 | being referred to from the filename source. | ||
1731 | |||
1732 | >>> make_relative_path('/usr/share/something/a-file.pth', | ||
1733 | ... '/usr/share/another-place/src/Directory') | ||
1734 | '../another-place/src/Directory' | ||
1735 | >>> make_relative_path('/usr/share/something/a-file.pth', | ||
1736 | ... '/home/user/src/Directory') | ||
1737 | '../../../home/user/src/Directory' | ||
1738 | >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/') | ||
1739 | './' | ||
1740 | """ | ||
1741 | source = os.path.dirname(source) | ||
1742 | if not dest_is_directory: | ||
1743 | dest_filename = os.path.basename(dest) | ||
1744 | dest = os.path.dirname(dest) | ||
1745 | dest = os.path.normpath(os.path.abspath(dest)) | ||
1746 | source = os.path.normpath(os.path.abspath(source)) | ||
1747 | dest_parts = dest.strip(os.path.sep).split(os.path.sep) | ||
1748 | source_parts = source.strip(os.path.sep).split(os.path.sep) | ||
1749 | while dest_parts and source_parts and dest_parts[0] == source_parts[0]: | ||
1750 | dest_parts.pop(0) | ||
1751 | source_parts.pop(0) | ||
1752 | full_parts = ['..']*len(source_parts) + dest_parts | ||
1753 | if not dest_is_directory: | ||
1754 | full_parts.append(dest_filename) | ||
1755 | if not full_parts: | ||
1756 | # Special case for the current directory (otherwise it'd be '') | ||
1757 | return './' | ||
1758 | return os.path.sep.join(full_parts) | ||
1759 | |||
1760 | |||
1761 | |||
1762 | ############################################################ | ||
1763 | ## Bootstrap script creation: | ||
1764 | |||
1765 | def create_bootstrap_script(extra_text, python_version=''): | ||
1766 | """ | ||
1767 | Creates a bootstrap script, which is like this script but with | ||
1768 | extend_parser, adjust_options, and after_install hooks. | ||
1769 | |||
1770 | This returns a string that (written to disk of course) can be used | ||
1771 | as a bootstrap script with your own customizations. The script | ||
1772 | will be the standard virtualenv.py script, with your extra text | ||
1773 | added (your extra text should be Python code). | ||
1774 | |||
1775 | If you include these functions, they will be called: | ||
1776 | |||
1777 | ``extend_parser(optparse_parser)``: | ||
1778 | You can add or remove options from the parser here. | ||
1779 | |||
1780 | ``adjust_options(options, args)``: | ||
1781 | You can change options here, or change the args (if you accept | ||
1782 | different kinds of arguments, be sure you modify ``args`` so it is | ||
1783 | only ``[DEST_DIR]``). | ||
1784 | |||
1785 | ``after_install(options, home_dir)``: | ||
1786 | |||
1787 | After everything is installed, this function is called. This | ||
1788 | is probably the function you are most likely to use. An | ||
1789 | example would be:: | ||
1790 | |||
1791 | def after_install(options, home_dir): | ||
1792 | subprocess.call([join(home_dir, 'bin', 'easy_install'), | ||
1793 | 'MyPackage']) | ||
1794 | subprocess.call([join(home_dir, 'bin', 'my-package-script'), | ||
1795 | 'setup', home_dir]) | ||
1796 | |||
1797 | This example immediately installs a package, and runs a setup | ||
1798 | script from that package. | ||
1799 | |||
1800 | If you provide something like ``python_version='2.5'`` then the | ||
1801 | script will start with ``#!/usr/bin/env python2.5`` instead of | ||
1802 | ``#!/usr/bin/env python``. You can use this when the script must | ||
1803 | be run with a particular Python version. | ||
1804 | """ | ||
1805 | filename = __file__ | ||
1806 | if filename.endswith('.pyc'): | ||
1807 | filename = filename[:-1] | ||
1808 | with codecs.open(filename, 'r', encoding='utf-8') as f: | ||
1809 | content = f.read() | ||
1810 | py_exe = 'python%s' % python_version | ||
1811 | content = (('#!/usr/bin/env %s\n' % py_exe) | ||
1812 | + '## WARNING: This file is generated\n' | ||
1813 | + content) | ||
1814 | return content.replace('##EXT' 'END##', extra_text) | ||
1815 | |||
1816 | ##EXTEND## | ||
1817 | |||
1818 | def convert(s): | ||
1819 | b = base64.b64decode(s.encode('ascii')) | ||
1820 | return zlib.decompress(b).decode('utf-8') | ||
1821 | |||
1822 | ##file site.py | ||
1823 | SITE_PY = convert(""" | ||
1824 | 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 | ||
1964 | AVijEPwfucjncQ== | ||
1965 | """) | ||
1966 | |||
1967 | ##file activate.sh | ||
1968 | ACTIVATE_SH = convert(""" | ||
1969 | eJytVd9v2kAMfs9fYQLq2m4MscdNVKMqEkgtVIQxbeuUHolpTgsXdHehpT/+9/mSEBJS2MOaB0ji | ||
1970 | z77P9menDpOAK5jzEGERKw0zhFihD/dcB2CrKJYewoyLFvM0XzGNNpzOZbSAGVPBqVWHdRSDx4SI | ||
1971 | NMhYANfgc4meDteW5ePGC45P4MkCumKhUENzDsu1H3lw1vJx1RJxGMKns6O2lWDqINGgotAHFCsu | ||
1972 | I7FAoWHFJGezEFWGqsEvaD5C42naHb93X+A3+elYCgVaxgh8DmQAys9HL2SS0mIaWBgm7mTN/O3G | ||
1973 | kzu6vHCng/HkW/fSve5O+hTOpnhfQAcoEry5jKVjNypoO0fgwzKSOgHm79KUK06Jfc7/RebHpD8a | ||
1974 | 9kdXvT2UcnuFWG6p0stNB0mWUUQ1q3uiGRVEMfXHR03dTuQATPjwqIIPcB9wL4CArRAY/ZHJixYL | ||
1975 | Y9YBtcAoLQtFevOoI9QaHcEdMSAB0d08kuZhyUiSmav6CPCdVBnFOjNrLu6yMCWgKRA0TInBC5i4 | ||
1976 | QwX3JG/mm581GKnSsSSxJTFHf9MAKr8w5T/vOv1mUurn5/zlT6fvTntjZzAaNl9rQ5JkU5KIc0GX | ||
1977 | inagwU57T2eddqWlTrvaS6d9sImZeUMkhWysveF0m37NcGub9Dpgi0j4qGiOzATjDr06OBjOYQOo | ||
1978 | 7RBoGtNm9Denv1i0LVI7lxJDXLHSSBeWRflsyyqw7diuW3h0XdvK6lBMyaoMG1UyHdTsoYBuue75 | ||
1979 | YOgOu1c91/2cwYpznPPeDoQpGL2xSm09NKp7BsvQ2hnT3aMs07lUnskpxewvBk73/LLnXo9HV9eT | ||
1980 | ijB3hWBO2ygoiWg/bKuZxqCCQq0DD3vkWIVvI2KosIw+vqW1gIItEG5KJb+xb09g65ktwYKgTc51 | ||
1981 | uGJ/EFQs0ayEWLCQM5V9N4g+1+8UbXOJzF8bqhKtIqIwicWvzNFROZJlpfD8A7Vc044R0FxkcezG | ||
1982 | VzsV75usvTdYef+57v5n1b225qhXfwEmxHEs | ||
1983 | """) | ||
1984 | |||
1985 | ##file activate.fish | ||
1986 | ACTIVATE_FISH = convert(""" | ||
1987 | eJyFVVFv2zYQftevuMoOnBS1gr0WGIZ08RADSRw4boBhGGhGOsUcKFIjKbUu9uN7lC2JsrXWDzZM | ||
1988 | fnf38e6+uwlsdsJCLiRCUVkHrwiVxYy+hHqDbQKvQl3z1ImaO0xyYXdbeP9FuJ1QwMFUSnmcP4dL | ||
1989 | 2DlXfry+9v/sDqVMUl3AFVi0Vmj1PokmcKtBaecNQTjIhMHUyX0SRXmlKIpWkGEbDuYZzBZfCVcL | ||
1990 | 4youUdVQ6AyBqwwMusoocBrcDsmpKbgEQgijVYHKJbMI6DMhoEUHWmbhLdTcCP4q0TYokYNDev5c | ||
1991 | QTxlq/tb9rJcbz7f3LOnm81d3GD8x3uav30FfwrnwCEOYRyAKot+FvXPzd3q8W71sBiJ3d2dMugu | ||
1992 | fsxjCPsBmz+Wz3fsab16eNqw1ctivV7eBnwm8EzeuQIsSrcHqVMqwHbqq8/aarKSO+oYKhKXUn9p | ||
1993 | SmWw0DVBdQ7bBlwaTR62bc+1tpaYb5PhUyScu48CRgvDLQbtMrMnMQ6dY5022JDRRrwJxWUfJwwP | ||
1994 | ge0YIAVGfcUC1M8s8MxitFZjmR9W64hui7p4fBlWMZ5y81b/9cvfMbz7FWZKq4yOTeW1hbNBEWU+ | ||
1995 | b+/ejXMu95lOx696uXb8Go4T+Kw8R2EMSqx5KLkkCkQ+ZBZFbZsHL4OYseAvY3EPO5MYTBuhDZQa | ||
1996 | TwPza8Y+LR/Z483Dgjwd4R3f7bTXx9Znkw6T6PAL83/hRD3jNAKFjuEx9NJkq5t+fabLvdvRwbw4 | ||
1997 | nEFTzwO6U+q34cvY7fL55tP94tg58XEA/q7LfdPsaUXFoEIMJdHF5iSW0+48CnDQ82G7n3XzAD6q | ||
1998 | Bmo5XuOA0NQ67ir7AXJtQhtLKO7XhC0l39PGOBsHPvzBuHUSjoOnA0ldozGC9gZ5rek3+y3ALHO/ | ||
1999 | kT7AP379lQZLSnFDLtwWihfYxw4nZd+ZR7myfkI2ZTRCuRxmF/bCzkbhcElvYamW9PbDGrvqPKC0 | ||
2000 | +D/uLi/sFcxGjOHylYagZzzsjjhw206RQwrWIwOxS2dnk+40xOjX8bTPegz/gdWVSXuaowNuOLda | ||
2001 | wYyNuRPSTcd/B48Ppeg= | ||
2002 | """) | ||
2003 | |||
2004 | ##file activate.csh | ||
2005 | ACTIVATE_CSH = convert(""" | ||
2006 | eJx1U2FP2zAQ/e5f8TAV3Soo+0zXbYUiDQkKQgVp2ibjJNfFUuIg22nVf885SVFLO3+I7Lt3fr6X | ||
2007 | d8eY58ZjYQpCWfuAhFB7yrAyIYf0Ve1SQmLsuU6DWepAw9TnEoOFq0rwdjAUx/hV1Ui1tVWAqy1M | ||
2008 | QGYcpaFYx+yVI67LkKwx1UuTEaYGl4X2Bl+zJpAlP/6V2hTDtCq/DYXQhdEeGW040Q/Eb+t9V/e3 | ||
2009 | U/V88zh/mtyqh8n8J47G+IKTE3gKZJdoYrK3h5MRU1tGYS83gqNc+3yEgyyP93cP820evHLvr2H8 | ||
2010 | kaYB/peoyY7aVHzpJnE9e+6I5Z+ji4GMTNJWNuOQq6MA1N25p8pW9HWdVWlfsNpPDbdxjgpaahuw | ||
2011 | 1M7opCA/FFu1uwxC7L8KUqmto1KyQe3rx0I0Eovdf7BVe67U5c1MzSZ310pddGheZoFPWyytRkzU | ||
2012 | aCA/I+RkBXhFXr5aWV0SxjhUI6jwdAj8kmhPzX7nTfJFkM3MImp2VdVFFq1vLHSU5szYQK4Ri+Jd | ||
2013 | xlW2JBtOGcyYVW7SnB3v6RS91g3gKapZ0oWxbHVteYIIq3iv7QeuSrUj6KSqQ+yqsxDj1ivNQxKF | ||
2014 | YON10Q+NH/ARS95i5Tuqq2Vxfvc23f/FO6zrtXXmJr+ZtMY9/A15ZXFWtmch2rEQ4g1ryVHH | ||
2015 | """) | ||
2016 | |||
2017 | ##file activate.bat | ||
2018 | ACTIVATE_BAT = convert(""" | ||
2019 | eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV | ||
2020 | mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O | ||
2021 | CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5 | ||
2022 | xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ | ||
2023 | MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U | ||
2024 | +g8CsNTr | ||
2025 | """) | ||
2026 | |||
2027 | ##file deactivate.bat | ||
2028 | DEACTIVATE_BAT = convert(""" | ||
2029 | eJyFkN0KgkAUhO8F32EQpHqFQEjQUPAPMaErqVxzId3IrV6/XST/UDx3c86c4WMO5FYysKJQFVVp | ||
2030 | CEfqxsnJ9DI7SA25i20fFqs3HO+GYLsDZ7h8GM3xfLHrg1QNvpSX4CWpQGvokZk4uqrQAjXjyElB | ||
2031 | a5IjCz0r+2dHcehHCe5MZNmB5R7TdqMqECMptHZh6DN/utb7Zs6Cej8OXYE5J04YOKFvD4GkHuJ0 | ||
2032 | pilSd1jG6n87tDZ+BUwUOepI6CGSkFMYWf0ihvT33Qj1A+tCkSI= | ||
2033 | """) | ||
2034 | |||
2035 | ##file activate.ps1 | ||
2036 | ACTIVATE_PS = convert(""" | ||
2037 | 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 | ||
2123 | rKQDxR6N/rffXv+lROXet/9Q+l9I4D1U | ||
2124 | """) | ||
2125 | |||
2126 | ##file distutils-init.py | ||
2127 | DISTUTILS_INIT = convert(""" | ||
2128 | eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E | ||
2129 | UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB | ||
2130 | C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss | ||
2131 | aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT | ||
2132 | 0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9 | ||
2133 | oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE | ||
2134 | NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c | ||
2135 | f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8 | ||
2136 | p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk | ||
2137 | vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw | ||
2138 | hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh | ||
2139 | cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw | ||
2140 | buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ | ||
2141 | 5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh | ||
2142 | gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC | ||
2143 | 1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL | ||
2144 | MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6 | ||
2145 | 84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK | ||
2146 | 0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO | ||
2147 | kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG | ||
2148 | qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h | ||
2149 | kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9 | ||
2150 | GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ= | ||
2151 | """) | ||
2152 | |||
2153 | ##file distutils.cfg | ||
2154 | DISTUTILS_CFG = convert(""" | ||
2155 | eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH | ||
2156 | xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg | ||
2157 | 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q= | ||
2158 | """) | ||
2159 | |||
2160 | ##file activate_this.py | ||
2161 | ACTIVATE_THIS = convert(""" | ||
2162 | eJyNU01v2zAMvetXEB4K21jnDOstQA4dMGCHbeihlyEIDMWmE62yJEiKE//7kXKdpEWLzYBt8evx | ||
2163 | kRSzLPs6wiEoswM8YdMpjUXcq1Dz6RZa1cSiTkJdr86GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe | ||
2164 | 5a3p0cRKiEe2NtLAFikftnDco0ko/SFEVgEZ8aRCZDIPY9xbA8pE9M4jfW/B2CjiHq9zbJVZuOQq | ||
2165 | siwTIvpxKYCembPAU4Muwi/Z4zfvrZ/MXipKeB8C+qisSZYiWfjJfs+0/MFMdWn1hJcO5U7G/SLa | ||
2166 | xVx8zU6VG/PXLXvfsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCJN9dzKaoexyB/uH79TnjwvxcW0ntSb | ||
2167 | yZ8jq1Z5Q1UXsyy3gf9nbjTEj7NzQMfCJa/YSmrQ+2D/BqfiOi6sclrGzvoeVivIj8rcfcmnIQRF | ||
2168 | 7XCyeZI7DFe5/lhlCs5PRf5QW66VXT/NrlQ46oD/D6InkOmi3IQcbhKxAX2g4a+Xd5s3UtCtG2py | ||
2169 | m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC | ||
2170 | 6wNEm1QdDZtuSZcEprIUBo/XRNcbQe1OUbQ/r3hPTaPJJDNtFLu8KHV5XoNr3Eo6h6YtOKw8e8yw | ||
2171 | VF5PnJ+ts3a9/Mz38RpG/AUSzYUW | ||
2172 | """) | ||
2173 | |||
2174 | ##file python-config | ||
2175 | PYTHON_CONFIG = convert(""" | ||
2176 | eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue | ||
2177 | e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll | ||
2178 | rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn | ||
2179 | 3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/ | ||
2180 | dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7 | ||
2181 | PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM | ||
2182 | osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT | ||
2183 | /mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad | ||
2184 | 0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1 | ||
2185 | 1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV | ||
2186 | 8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE | ||
2187 | LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl | ||
2188 | g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD | ||
2189 | /vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9 | ||
2190 | MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA== | ||
2191 | """) | ||
2192 | |||
2193 | MH_MAGIC = 0xfeedface | ||
2194 | MH_CIGAM = 0xcefaedfe | ||
2195 | MH_MAGIC_64 = 0xfeedfacf | ||
2196 | MH_CIGAM_64 = 0xcffaedfe | ||
2197 | FAT_MAGIC = 0xcafebabe | ||
2198 | BIG_ENDIAN = '>' | ||
2199 | LITTLE_ENDIAN = '<' | ||
2200 | LC_LOAD_DYLIB = 0xc | ||
2201 | maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') | ||
2202 | |||
2203 | |||
2204 | class fileview(object): | ||
2205 | """ | ||
2206 | A proxy for file-like objects that exposes a given view of a file. | ||
2207 | Modified from macholib. | ||
2208 | """ | ||
2209 | |||
2210 | def __init__(self, fileobj, start=0, size=maxint): | ||
2211 | if isinstance(fileobj, fileview): | ||
2212 | self._fileobj = fileobj._fileobj | ||
2213 | else: | ||
2214 | self._fileobj = fileobj | ||
2215 | self._start = start | ||
2216 | self._end = start + size | ||
2217 | self._pos = 0 | ||
2218 | |||
2219 | def __repr__(self): | ||
2220 | return '<fileview [%d, %d] %r>' % ( | ||
2221 | self._start, self._end, self._fileobj) | ||
2222 | |||
2223 | def tell(self): | ||
2224 | return self._pos | ||
2225 | |||
2226 | def _checkwindow(self, seekto, op): | ||
2227 | if not (self._start <= seekto <= self._end): | ||
2228 | raise IOError("%s to offset %d is outside window [%d, %d]" % ( | ||
2229 | op, seekto, self._start, self._end)) | ||
2230 | |||
2231 | def seek(self, offset, whence=0): | ||
2232 | seekto = offset | ||
2233 | if whence == os.SEEK_SET: | ||
2234 | seekto += self._start | ||
2235 | elif whence == os.SEEK_CUR: | ||
2236 | seekto += self._start + self._pos | ||
2237 | elif whence == os.SEEK_END: | ||
2238 | seekto += self._end | ||
2239 | else: | ||
2240 | raise IOError("Invalid whence argument to seek: %r" % (whence,)) | ||
2241 | self._checkwindow(seekto, 'seek') | ||
2242 | self._fileobj.seek(seekto) | ||
2243 | self._pos = seekto - self._start | ||
2244 | |||
2245 | def write(self, bytes): | ||
2246 | here = self._start + self._pos | ||
2247 | self._checkwindow(here, 'write') | ||
2248 | self._checkwindow(here + len(bytes), 'write') | ||
2249 | self._fileobj.seek(here, os.SEEK_SET) | ||
2250 | self._fileobj.write(bytes) | ||
2251 | self._pos += len(bytes) | ||
2252 | |||
2253 | def read(self, size=maxint): | ||
2254 | assert size >= 0 | ||
2255 | here = self._start + self._pos | ||
2256 | self._checkwindow(here, 'read') | ||
2257 | size = min(size, self._end - here) | ||
2258 | self._fileobj.seek(here, os.SEEK_SET) | ||
2259 | bytes = self._fileobj.read(size) | ||
2260 | self._pos += len(bytes) | ||
2261 | return bytes | ||
2262 | |||
2263 | |||
2264 | def read_data(file, endian, num=1): | ||
2265 | """ | ||
2266 | Read a given number of 32-bits unsigned integers from the given file | ||
2267 | with the given endianness. | ||
2268 | """ | ||
2269 | res = struct.unpack(endian + 'L' * num, file.read(num * 4)) | ||
2270 | if len(res) == 1: | ||
2271 | return res[0] | ||
2272 | return res | ||
2273 | |||
2274 | |||
2275 | def mach_o_change(path, what, value): | ||
2276 | """ | ||
2277 | Replace a given name (what) in any LC_LOAD_DYLIB command found in | ||
2278 | the given binary with a new name (value), provided it's shorter. | ||
2279 | """ | ||
2280 | |||
2281 | def do_macho(file, bits, endian): | ||
2282 | # Read Mach-O header (the magic number is assumed read by the caller) | ||
2283 | cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6) | ||
2284 | # 64-bits header has one more field. | ||
2285 | if bits == 64: | ||
2286 | read_data(file, endian) | ||
2287 | # The header is followed by ncmds commands | ||
2288 | for n in range(ncmds): | ||
2289 | where = file.tell() | ||
2290 | # Read command header | ||
2291 | cmd, cmdsize = read_data(file, endian, 2) | ||
2292 | if cmd == LC_LOAD_DYLIB: | ||
2293 | # The first data field in LC_LOAD_DYLIB commands is the | ||
2294 | # offset of the name, starting from the beginning of the | ||
2295 | # command. | ||
2296 | name_offset = read_data(file, endian) | ||
2297 | file.seek(where + name_offset, os.SEEK_SET) | ||
2298 | # Read the NUL terminated string | ||
2299 | load = file.read(cmdsize - name_offset).decode() | ||
2300 | load = load[:load.index('\0')] | ||
2301 | # If the string is what is being replaced, overwrite it. | ||
2302 | if load == what: | ||
2303 | file.seek(where + name_offset, os.SEEK_SET) | ||
2304 | file.write(value.encode() + '\0'.encode()) | ||
2305 | # Seek to the next command | ||
2306 | file.seek(where + cmdsize, os.SEEK_SET) | ||
2307 | |||
2308 | def do_file(file, offset=0, size=maxint): | ||
2309 | file = fileview(file, offset, size) | ||
2310 | # Read magic number | ||
2311 | magic = read_data(file, BIG_ENDIAN) | ||
2312 | if magic == FAT_MAGIC: | ||
2313 | # Fat binaries contain nfat_arch Mach-O binaries | ||
2314 | nfat_arch = read_data(file, BIG_ENDIAN) | ||
2315 | for n in range(nfat_arch): | ||
2316 | # Read arch header | ||
2317 | cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5) | ||
2318 | do_file(file, offset, size) | ||
2319 | elif magic == MH_MAGIC: | ||
2320 | do_macho(file, 32, BIG_ENDIAN) | ||
2321 | elif magic == MH_CIGAM: | ||
2322 | do_macho(file, 32, LITTLE_ENDIAN) | ||
2323 | elif magic == MH_MAGIC_64: | ||
2324 | do_macho(file, 64, BIG_ENDIAN) | ||
2325 | elif magic == MH_CIGAM_64: | ||
2326 | do_macho(file, 64, LITTLE_ENDIAN) | ||
2327 | |||
2328 | assert(len(what) >= len(value)) | ||
2329 | |||
2330 | with open(path, 'r+b') as f: | ||
2331 | do_file(f) | ||
2332 | |||
2333 | |||
2334 | if __name__ == '__main__': | ||
2335 | main() | ||
2336 | |||
2337 | # TODO: | ||
2338 | # Copy python.exe.manifest | ||
2339 | # Monkeypatch distutils.sysconfig | ||