-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstaller.py
More file actions
128 lines (105 loc) · 3.73 KB
/
Copy pathinstaller.py
File metadata and controls
128 lines (105 loc) · 3.73 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import re
import io
import os
import requests
import zipfile
import stat
from pathlib import Path
from distutils.util import get_platform
tag = re.compile('refs/tags/v(\S+)')
def make_executable(cmd_path):
# always modify mode to READ + EXEC
os.chmod(cmd_path, stat.S_IREAD | stat.S_IEXEC)
def show_tags(url=r"https://github.com/purescript-python/purescript-python"):
"""
Use ls-remote in gitPython
https://stackoverflow.com/questions/35585236/git-ls-remote-in-gitpython
"""
import git
g = git.cmd.Git()
for ref in g.ls_remote(url).split('\n'):
found = tag.findall(ref.split('\t')[-1].strip())
if not found:
continue
yield found[0]
def mk_tmplt(template):
if isinstance(template, dict):
def check(data,
*,
tmplt=tuple((k, mk_tmplt(v)) for k, v in template.items())):
if not isinstance(data, dict):
return False
for k, v in tmplt:
if k not in data:
return False
if not v(data[k]):
return False
return True
elif isinstance(template, list):
def check(data, *, tmplt=tuple(map(mk_tmplt, template))):
if not isinstance(data, list):
return False
if len(data) != len(tmplt):
return False
for t, v in zip(tmplt, data):
if not t(v):
return False
return True
elif isinstance(template, type):
def check(data, *, t=template):
return isinstance(data, t)
elif template is any:
check = lambda _: True
elif hasattr(template, 'match'):
check = template.match
else:
def check(data, *, o=template):
return data == o
return check
def traverse(f, data):
if isinstance(data, dict):
for each in data.values():
yield from traverse(f, each)
elif isinstance(data, list):
for each in data:
yield from traverse(f, each)
if f(data):
yield data
def gq(tmp, data):
return traverse(mk_tmplt(tmp), data)
def get_binary(out_path):
"""out_path is the directory of executable, instead of the path
"""
if isinstance(out_path, str):
out_path = Path(out_path)
elif not isinstance(out_path, Path):
raise TypeError(type(out_path))
from purescripto.version import __blueprint_version__
max_fit_tag = max(filter(lambda x: x.startswith(__blueprint_version__), show_tags()))
print('Downloading binaries from purescript-python/purescript-python...')
data = requests.get(
r"https://api.github.com/repos/purescript-python/purescript-python/releases/tags/v{}"
.format(max_fit_tag)).json()
print('Binaries downloaded.')
plat_name = get_platform()
matcher = re.compile('\S+' + re.escape(plat_name))
tmplt = {'browser_download_url': matcher}
try:
each = next(gq(tmplt, data))
except StopIteration:
import sys
print(
"It seems that binaries for your platform is not available.\n"
"Following way must work, but can be quite time-consuming:\n"
"Firstly, Install Haskell Stack Build Tool: https://docs.haskellstack.org/en/stable/README/\n"
"Second, Clone https://github.com/purescript-python/purescript-python, then do `stack install .`"
)
sys.exit(1)
url = each['browser_download_url']
zf = zipfile.ZipFile(io.BytesIO(requests.get(url).content))
exe = "pspy-blueprint"
if 'win' in url:
exe += '.exe'
out_path.mkdir(exist_ok=True, parents=True, mode=0o777)
zf.extract(exe, path=str(out_path))
make_executable(str(out_path / exe))