Skip to content

Commit 7f48586

Browse files
author
Christopher Doris
committed
working on removing jill dependency
1 parent a49659c commit 7f48586

File tree

4 files changed

+179
-7
lines changed

4 files changed

+179
-7
lines changed

juliacall/deps.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from time import time
66

77
from . import CONFIG, __version__
8-
from .jlcompat import JuliaCompat, Version, julia_version_str
8+
from .semver import JuliaCompat, Version, julia_version_str
99

1010
### META
1111

juliacall/init.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import os, os.path, ctypes as c, shutil, subprocess, jill.install as jli
2-
from . import CONFIG, __version__, deps, jlcompat
2+
from . import CONFIG, __version__, deps, semver
33

44
# Determine if this is a development version of juliacall
55
# i.e. it is installed from the github repo, which contains Project.toml
@@ -50,7 +50,7 @@
5050
# Find the Julia executable
5151
exepath = os.environ.get('PYTHON_JULIACALL_EXE')
5252
if exepath is not None:
53-
v = jlcompat.julia_version_str(exepath)
53+
v = semver.julia_version_str(exepath)
5454
if v is None:
5555
raise ValueError("PYTHON_JULIACALL_EXE={!r} does not exist".format(exepath))
5656
else:
@@ -66,14 +66,14 @@
6666
exepath = None
6767
jill_upstream = os.getenv("JILL_UPSTREAM") or "Official"
6868
exever = deps.best_julia_version(compat, upstream=jill_upstream)
69-
v = jlcompat.julia_version_str("julia")
69+
v = semver.julia_version_str("julia")
7070
if v is not None and v == exever:
7171
exepath = "julia"
7272
elif os.path.isdir(jlbin):
7373
for f in os.listdir(jlbin):
7474
if f.startswith("julia"):
7575
x = os.path.join(jlbin, f)
76-
v = jlcompat.julia_version_str(x)
76+
v = semver.julia_version_str(x)
7777
if v is not None and v == exever:
7878
exepath = x
7979
break
@@ -100,8 +100,8 @@
100100
if not os.path.isfile(exepath):
101101
raise Exception('Installed julia in {!r} but cannot find it'.format(jlbin))
102102
# Check the version is compatible
103-
v = jlcompat.julia_version_str(exepath)
104-
assert v is not None and (compat is None or jlcompat.Version(v) in compat)
103+
v = semver.julia_version_str(exepath)
104+
assert v is not None and (compat is None or semver.Version(v) in compat)
105105
CONFIG['exever'] = v
106106
CONFIG['exepath'] = exepath
107107
libpath = subprocess.run([exepath, '--startup-file=no', '-O0', '--compile=min', '-e', 'import Libdl; print(abspath(Libdl.dlpath("libjulia")))'], stdout=(subprocess.PIPE)).stdout.decode('utf8')

juliacall/install.py

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
import hashlib
2+
import io
3+
import json
4+
import os
5+
import platform
6+
import shutil
7+
import tarfile
8+
import time
9+
import urllib.request
10+
import warnings
11+
import zipfile
12+
13+
from .semver import Version
14+
15+
_all_julia_versions = None
16+
17+
def all_julia_versions():
18+
global _all_julia_versions
19+
if _all_julia_versions is None:
20+
url = 'https://julialang-s3.julialang.org/bin/versions.json'
21+
print(f'Querying Julia versions from {url}')
22+
with urllib.request.urlopen(url) as f:
23+
_all_julia_versions = json.loads(f.read())
24+
return _all_julia_versions
25+
26+
os_aliases = {
27+
'darwin': 'mac',
28+
'windows': 'winnt',
29+
}
30+
31+
def get_os():
32+
os = platform.system()
33+
return os_aliases.get(os.lower(), os)
34+
35+
arch_aliases = {
36+
'arm64': 'aarch64',
37+
'i386': 'i686',
38+
'amd64': 'x86_64',
39+
}
40+
41+
def get_arch():
42+
arch = platform.machine()
43+
return arch_aliases.get(arch.lower(), arch)
44+
45+
def compatible_julia_versions(compat=None, stable=True, kind=None):
46+
os = get_os()
47+
arch = get_arch()
48+
libc, _ = platform.libc_ver()
49+
if libc == '' and os == 'linux':
50+
warnings.warn('could not determine libc version - assuming glibc')
51+
libc = 'gnu'
52+
ans = {}
53+
for (k, v) in all_julia_versions().items():
54+
v = v.copy()
55+
if stable is not None and v['stable'] != stable:
56+
continue
57+
files = []
58+
for f in v['files']:
59+
assert f['version'] == k
60+
if kind is not None and f['kind'] != kind:
61+
continue
62+
if f['os'] != os:
63+
continue
64+
if f['arch'] != arch:
65+
continue
66+
if os == 'linux' and f['triplet'].split('-')[2] != libc:
67+
continue
68+
if compat is not None:
69+
try:
70+
ver = Version(f['version'])
71+
except Exception:
72+
continue
73+
if ver not in compat:
74+
continue
75+
files.append(f)
76+
if not files:
77+
continue
78+
v['files'] = files
79+
ans[k] = v
80+
triplets = {f['triplet'] for (k, v) in ans.items() for f in v['files']}
81+
if len(triplets) > 1:
82+
raise Exception(f'multiple matching triplets {sorted(triplets)} - this is a bug, please report')
83+
return ans
84+
85+
def best_julia_version(*args, **kwargs):
86+
vers = compatible_julia_versions(*args, **kwargs)
87+
if not vers:
88+
raise ValueError('no compatible Julia version found')
89+
v = sorted(vers.keys(), key=Version)[-1]
90+
return v, vers[v]
91+
92+
def install_julia(ver, prefix):
93+
for f in ver['files']:
94+
url = f['url']
95+
if url.endswith('.tar.gz'):
96+
installer = install_julia_tar
97+
elif url.endswith('.zip'):
98+
installer = install_julia_zip
99+
elif url.endswith('.dmg'):
100+
installer = install_julia_dmg
101+
else:
102+
continue
103+
buf = download_julia(f)
104+
print(f'Installing Julia to {prefix}')
105+
if os.path.exists(prefix):
106+
shutil.rmtree(prefix)
107+
installer(f, buf, prefix)
108+
return
109+
raise ValueError('no installable Julia version found')
110+
111+
def download_julia(f):
112+
url = f['url']
113+
sha256 = f['sha256']
114+
size = f['size']
115+
print(f'Downloading Julia from {url}')
116+
buf = io.BytesIO()
117+
freq = 5
118+
t = time.time() + freq
119+
with urllib.request.urlopen(url) as f:
120+
while True:
121+
data = f.read(1<<16)
122+
if not data:
123+
break
124+
buf.write(data)
125+
if time.time() > t:
126+
print(f' downloaded {buf.tell()/(1<<20):.3f} MB of {size/(1<<20):.3f} MB')
127+
t = time.time() + freq
128+
print(' download complete')
129+
print(f'Verifying download')
130+
buf.seek(0)
131+
m = hashlib.sha256()
132+
m.update(buf.read())
133+
sha256actual = m.hexdigest()
134+
if sha256actual != sha256:
135+
raise Exception(f'SHA-256 hash does not match, got {sha256actual}, expecting {sha256}')
136+
buf.seek(0)
137+
return buf
138+
139+
def install_julia_zip(f, buf, prefix):
140+
os.makedirs(prefix)
141+
with zipfile.ZipFile(buf) as zf:
142+
zf.extractall(prefix)
143+
fns = os.listdir(prefix)
144+
if 'bin' not in fns:
145+
if len(fns) != 1:
146+
raise Exception('expecting one subdirectory')
147+
top = fns[0]
148+
fns = os.listdir(os.path.join(prefix, top))
149+
if 'bin' not in fns:
150+
raise Exception('expecting a bin directory')
151+
for fn in fns:
152+
os.rename(os.path.join(prefix, top, fn), os.path.join(prefix, fn))
153+
os.rmdir(os.path.join(prefix, top))
154+
155+
def install_julia_tar(f, buf, prefix):
156+
os.makedirs(prefix)
157+
with tarfile.TarFile(fileobj=buf) as tf:
158+
tf.extractall(prefix)
159+
fns = os.listdir(prefix)
160+
if 'bin' not in fns:
161+
if len(fns) != 1:
162+
raise Exception('expecting one subdirectory')
163+
top = fns[0]
164+
fns = os.listdir(os.path.join(prefix, top))
165+
if 'bin' not in fns:
166+
raise Exception('expecting a bin directory')
167+
for fn in fns:
168+
os.rename(os.path.join(prefix, top, fn), os.path.join(prefix, fn))
169+
os.rmdir(os.path.join(prefix, top))
170+
171+
def install_julia_dmg(f, buf, prefix):
172+
raise NotImplementedError('cannot yet install Julia from DMG')
File renamed without changes.

0 commit comments

Comments
 (0)