Skip to content

Commit 1e88005

Browse files
author
Christopher Doris
committed
install julia
1 parent 6d71cec commit 1e88005

File tree

1 file changed

+74
-71
lines changed

1 file changed

+74
-71
lines changed

juliacall/install.py

Lines changed: 74 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import shutil
88
import subprocess
99
import tarfile
10+
import tempfile
1011
import time
1112
import urllib.request
1213
import warnings
@@ -52,7 +53,7 @@ def get_libc():
5253
libc = platform.libc_ver()[0].lower()
5354
return libc_aliases.get(libc, libc)
5455

55-
def compatible_julia_versions(compat=None, stable=True, kind=None):
56+
def compatible_julia_versions(compat=None):
5657
os = get_os()
5758
arch = get_arch()
5859
libc = get_libc()
@@ -62,12 +63,12 @@ def compatible_julia_versions(compat=None, stable=True, kind=None):
6263
ans = {}
6364
for (k, v) in all_julia_versions().items():
6465
v = v.copy()
65-
if stable is not None and v['stable'] != stable:
66+
if not v['stable']:
6667
continue
6768
files = []
6869
for f in v['files']:
6970
assert f['version'] == k
70-
if kind is not None and f['kind'] != kind:
71+
if not any(f['url'].endswith(ext) for ext in julia_installers):
7172
continue
7273
if f['os'] != os:
7374
continue
@@ -92,27 +93,34 @@ def compatible_julia_versions(compat=None, stable=True, kind=None):
9293
raise Exception(f'multiple matching triplets {sorted(triplets)} - this is a bug, please report')
9394
return ans
9495

95-
def install_julia(vers, prefix):
96+
def best_julia_version(compat=None):
97+
vers = compatible_julia_versions(compat)
9698
if not vers:
9799
raise Exception('no compatible Julia version found')
98-
for v in sorted(vers.keys(), key=Version, reverse=True):
99-
for f in vers[v]['files']:
100-
url = f['url']
101-
if url.endswith('.tar.gz'):
102-
installer = install_julia_tar_gz
103-
elif url.endswith('.zip'):
104-
installer = install_julia_zip
105-
elif url.endswith('.dmg'):
106-
installer = install_julia_dmg
107-
else:
108-
continue
109-
buf = download_julia(f)
110-
prefix2 = prefix.format(version=v)
111-
print(f'Installing Julia to {prefix2}')
112-
if os.path.exists(prefix2):
113-
shutil.rmtree(prefix2)
114-
installer(f, buf, prefix2)
115-
return
100+
v = sorted(vers.keys(), key=Version, reverse=True)[0]
101+
return v, vers[v]
102+
103+
def install_julia(ver, prefix):
104+
for f in ver['files']:
105+
url = f['url']
106+
# find a suitable installer
107+
installer = None
108+
for ext in julia_installers:
109+
if url.endswith(ext):
110+
installer = julia_installers[ext]
111+
break
112+
if installer is None:
113+
continue
114+
# download julia
115+
buf = download_julia(f)
116+
# include the version in the prefix
117+
print(f'Installing Julia to {prefix}')
118+
if os.path.exists(prefix):
119+
shutil.rmtree(prefix)
120+
if os.path.dirname(prefix):
121+
os.makedirs(os.path.dirname(prefix))
122+
installer(f, buf, prefix)
123+
return
116124
raise Exception('no installable Julia version found')
117125

118126
def download_julia(f):
@@ -130,7 +138,7 @@ def download_julia(f):
130138
break
131139
buf.write(data)
132140
if time.time() > t:
133-
print(f' downloaded {buf.tell()/(1<<20):.3f} MB of {size/(1<<20):.3f} MB')
141+
print(f' downloaded {buf.tell()/(1<<20):.1f} MB of {size/(1<<20):.1f} MB')
134142
t = time.time() + freq
135143
print(' download complete')
136144
print(f'Verifying download')
@@ -144,55 +152,50 @@ def download_julia(f):
144152
return buf
145153

146154
def install_julia_zip(f, buf, prefix):
147-
os.makedirs(prefix)
148-
with zipfile.ZipFile(buf) as zf:
149-
zf.extractall(prefix)
150-
fns = os.listdir(prefix)
151-
if 'bin' not in fns:
152-
if len(fns) != 1:
153-
raise Exception('expecting one subdirectory')
154-
top = fns[0]
155-
fns = os.listdir(os.path.join(prefix, top))
156-
if 'bin' not in fns:
157-
raise Exception('expecting a bin directory')
158-
for fn in fns:
159-
os.rename(os.path.join(prefix, top, fn), os.path.join(prefix, fn))
160-
os.rmdir(os.path.join(prefix, top))
155+
with tempfile.TemporaryDirectory() as tmpdir:
156+
# extract all files
157+
with zipfile.ZipFile(buf) as zf:
158+
zf.extractall(tmpdir)
159+
# copy stuff out
160+
srcdirs = [d for d in os.listdir(tmpdir) if d.startswith('julia')]
161+
if len(srcdirs) != 1:
162+
raise Exception('expecting one julia* directory')
163+
shutil.copytree(os.path.join(tmpdir, srcdirs[0]), prefix, symlinks=True)
161164

162165
def install_julia_tar_gz(f, buf, prefix):
163-
os.makedirs(prefix)
164-
with gzip.GzipFile(fileobj=buf) as gf:
165-
with tarfile.TarFile(fileobj=gf) as tf:
166-
tf.extractall(prefix)
167-
fns = os.listdir(prefix)
168-
if 'bin' not in fns:
169-
if len(fns) != 1:
170-
raise Exception('expecting one subdirectory')
171-
top = fns[0]
172-
fns = os.listdir(os.path.join(prefix, top))
173-
if 'bin' not in fns:
174-
raise Exception('expecting a bin directory')
175-
for fn in fns:
176-
os.rename(os.path.join(prefix, top, fn), os.path.join(prefix, fn))
177-
os.rmdir(os.path.join(prefix, top))
166+
with tempfile.TemporaryDirectory() as tmpdir:
167+
# extract all files
168+
with gzip.GzipFile(fileobj=buf) as gf:
169+
with tarfile.TarFile(fileobj=gf) as tf:
170+
tf.extractall(tmpdir)
171+
# copy stuff out
172+
srcdirs = [d for d in os.listdir(tmpdir) if d.startswith('julia')]
173+
if len(srcdirs) != 1:
174+
raise Exception('expecting one julia* directory')
175+
shutil.copytree(os.path.join(tmpdir, srcdirs[0]), prefix, symlinks=True)
178176

179177
def install_julia_dmg(f, buf, prefix):
180-
tmpdir = prefix + '.tmp'
181-
os.makedirs(tmpdir)
182-
# write the dmg file out
183-
dmg = os.path.join(tmpdir, 'dmg')
184-
with open(dmg, 'wb') as f:
185-
f.write(buf.read())
186-
# mount it
187-
mount = os.path.join(tmpdir, 'mount')
188-
subprocess.run(['hdiutil', 'mount', '-mount', 'required', '-mountpoint', mount, dmg], check=True, capture_output=True)
189-
# copy stuff out
190-
appdirs = [d for d in os.listdir(mount) if d.startswith('Julia') and d.endswith('.app')]
191-
if len(appdirs) != 1:
192-
raise Exception('expecting one Julia*.app directory')
193-
srcdir = os.path.join(mount, appdirs[0], 'Contents', 'Resources', 'julia')
194-
shutil.copytree(srcdir, prefix, symlinks=True)
195-
# unmount
196-
subprocess.run(['umount', mount], check=True, capture_output=True)
197-
# delete tmpdir
198-
shutil.rmtree(tmpdir)
178+
with tempfile.TemporaryDirectory() as tmpdir:
179+
# write the dmg file out
180+
dmg = os.path.join(tmpdir, 'dmg')
181+
with open(dmg, 'wb') as f:
182+
f.write(buf.read())
183+
# mount it
184+
mount = os.path.join(tmpdir, 'mount')
185+
subprocess.run(['hdiutil', 'mount', '-mount', 'required', '-mountpoint', mount, dmg], check=True, capture_output=True)
186+
try:
187+
# copy stuff out
188+
appdirs = [d for d in os.listdir(mount) if d.startswith('Julia') and d.endswith('.app')]
189+
if len(appdirs) != 1:
190+
raise Exception('expecting one Julia*.app directory')
191+
srcdir = os.path.join(mount, appdirs[0], 'Contents', 'Resources', 'julia')
192+
shutil.copytree(srcdir, prefix, symlinks=True)
193+
finally:
194+
# unmount
195+
subprocess.run(['umount', mount], check=True, capture_output=True)
196+
197+
julia_installers = {
198+
'.tar.gz': install_julia_tar_gz,
199+
'.zip': install_julia_zip,
200+
'.dmg': install_julia_dmg,
201+
}

0 commit comments

Comments
 (0)