• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# coding: utf-8
2from __future__ import unicode_literals, division, absolute_import, print_function
3
4import os
5import subprocess
6import sys
7
8
9run_args = [
10    {
11        'name': 'version',
12        'kwarg': 'version',
13    },
14]
15
16
17def _write_env(env, key, value):
18    sys.stdout.write("%s: %s\n" % (key, value))
19    sys.stdout.flush()
20    if sys.version_info < (3,):
21        env[key.encode('utf-8')] = value.encode('utf-8')
22    else:
23        env[key] = value
24
25
26def run(version=None):
27    """
28    Installs a version of Python on Mac using pyenv
29
30    :return:
31        A bool - if Python was installed successfully
32    """
33
34    if sys.platform == 'win32':
35        raise ValueError('pyenv-install is not designed for Windows')
36
37    if version not in set(['2.6', '3.3']):
38        raise ValueError('Invalid version: %r' % version)
39
40    python_path = os.path.expanduser('~/.pyenv/versions/%s/bin' % version)
41    if os.path.exists(os.path.join(python_path, 'python')):
42        print(python_path)
43        return True
44
45    stdout = ""
46    stderr = ""
47
48    proc = subprocess.Popen(
49        'command -v pyenv',
50        shell=True,
51        stdout=subprocess.PIPE,
52        stderr=subprocess.PIPE
53    )
54    proc.communicate()
55    if proc.returncode != 0:
56        proc = subprocess.Popen(
57            ['brew', 'install', 'pyenv'],
58            stdout=subprocess.PIPE,
59            stderr=subprocess.PIPE
60        )
61        so, se = proc.communicate()
62        stdout += so.decode('utf-8')
63        stderr += se.decode('utf-8')
64        if proc.returncode != 0:
65            print(stdout)
66            print(stderr, file=sys.stderr)
67            return False
68
69    pyenv_script = './%s' % version
70    try:
71        with open(pyenv_script, 'wb') as f:
72            if version == '2.6':
73                contents = '#require_gcc\n' \
74                    'install_package "openssl-1.0.2k" "https://www.openssl.org/source/old/1.0.2/openssl-1.0.2k.tar.gz' \
75                    '#6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0" mac_openssl\n' \
76                    'install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz' \
77                    '#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline' \
78                    ' --if has_broken_mac_readline\n' \
79                    'install_package "Python-2.6.9" "https://www.python.org/ftp/python/2.6.9/Python-2.6.9.tgz' \
80                    '#7277b1285d8a82f374ef6ebaac85b003266f7939b3f2a24a3af52f9523ac94db" standard verify_py26'
81            elif version == '3.3':
82                contents = '#require_gcc\n' \
83                    'install_package "openssl-1.0.2k" "https://www.openssl.org/source/old/1.0.2/openssl-1.0.2k.tar.gz' \
84                    '#6b3977c61f2aedf0f96367dcfb5c6e578cf37e7b8d913b4ecb6643c3cb88d8c0" mac_openssl\n' \
85                    'install_package "readline-8.0" "https://ftpmirror.gnu.org/readline/readline-8.0.tar.gz' \
86                    '#e339f51971478d369f8a053a330a190781acb9864cf4c541060f12078948e461" mac_readline' \
87                    ' --if has_broken_mac_readline\n' \
88                    'install_package "Python-3.3.7" "https://www.python.org/ftp/python/3.3.7/Python-3.3.7.tar.xz' \
89                    '#85f60c327501c36bc18c33370c14d472801e6af2f901dafbba056f61685429fe" standard verify_py33'
90            f.write(contents.encode('utf-8'))
91
92        args = ['pyenv', 'install', pyenv_script]
93        stdin = None
94        stdin_contents = None
95        env = os.environ.copy()
96
97        if version == '2.6':
98            _write_env(env, 'PYTHON_CONFIGURE_OPTS', '--enable-ipv6')
99            stdin = subprocess.PIPE
100            stdin_contents = '--- configure  2021-08-05 20:17:26.000000000 -0400\n' \
101                '+++ configure   2021-08-05 20:21:30.000000000 -0400\n' \
102                '@@ -10300,17 +10300,8 @@\n' \
103                ' rm -f core conftest.err conftest.$ac_objext \\\n' \
104                '     conftest$ac_exeext conftest.$ac_ext\n' \
105                ' \n' \
106                '-if test "$buggygetaddrinfo" = "yes"; then\n' \
107                '-\tif test "$ipv6" = "yes"; then\n' \
108                '-\t\techo \'Fatal: You must get working getaddrinfo() function.\'\n' \
109                '-\t\techo \'       or you can specify "--disable-ipv6"\'.\n' \
110                '-\t\texit 1\n' \
111                '-\tfi\n' \
112                '-else\n' \
113                '-\n' \
114                ' $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h\n' \
115                ' \n' \
116                '-fi\n' \
117                ' for ac_func in getnameinfo\n' \
118                ' do :\n' \
119                '   ac_fn_c_check_func "$LINENO" "getnameinfo" "ac_cv_func_getnameinfo"'
120            stdin_contents = stdin_contents.encode('ascii')
121            args.append('--patch')
122
123        proc = subprocess.Popen(
124            args,
125            stdout=subprocess.PIPE,
126            stderr=subprocess.PIPE,
127            stdin=stdin,
128            env=env
129        )
130        so, se = proc.communicate(stdin_contents)
131        stdout += so.decode('utf-8')
132        stderr += se.decode('utf-8')
133
134        if proc.returncode != 0:
135            print(stdout)
136            print(stderr, file=sys.stderr)
137            return False
138
139    finally:
140        if os.path.exists(pyenv_script):
141            os.unlink(pyenv_script)
142
143    print(python_path)
144    return True
145