siliconcompiler 0.33.2__py3-none-any.whl → 0.34.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siliconcompiler/__init__.py +2 -0
- siliconcompiler/_metadata.py +1 -1
- siliconcompiler/apps/sc_issue.py +5 -3
- siliconcompiler/apps/sc_remote.py +0 -17
- siliconcompiler/checklist.py +1 -1
- siliconcompiler/core.py +34 -47
- siliconcompiler/dependencyschema.py +392 -0
- siliconcompiler/design.py +664 -0
- siliconcompiler/flowgraph.py +32 -1
- siliconcompiler/package/__init__.py +383 -223
- siliconcompiler/package/git.py +75 -77
- siliconcompiler/package/github.py +70 -97
- siliconcompiler/package/https.py +77 -93
- siliconcompiler/packageschema.py +260 -0
- siliconcompiler/pdk.py +2 -2
- siliconcompiler/remote/client.py +15 -3
- siliconcompiler/report/dashboard/cli/board.py +1 -1
- siliconcompiler/scheduler/__init__.py +3 -1382
- siliconcompiler/scheduler/docker.py +268 -0
- siliconcompiler/scheduler/run_node.py +10 -16
- siliconcompiler/scheduler/scheduler.py +308 -0
- siliconcompiler/scheduler/schedulernode.py +934 -0
- siliconcompiler/scheduler/slurm.py +147 -163
- siliconcompiler/scheduler/taskscheduler.py +39 -52
- siliconcompiler/schema/__init__.py +3 -3
- siliconcompiler/schema/baseschema.py +234 -10
- siliconcompiler/schema/editableschema.py +4 -0
- siliconcompiler/schema/journal.py +210 -0
- siliconcompiler/schema/namedschema.py +31 -2
- siliconcompiler/schema/parameter.py +14 -1
- siliconcompiler/schema/parametervalue.py +1 -34
- siliconcompiler/schema/schema_cfg.py +210 -349
- siliconcompiler/tool.py +61 -20
- siliconcompiler/tools/builtin/concatenate.py +2 -2
- siliconcompiler/tools/builtin/verify.py +1 -2
- siliconcompiler/tools/openroad/scripts/common/procs.tcl +27 -25
- siliconcompiler/tools/vpr/route.py +69 -0
- siliconcompiler/toolscripts/_tools.json +4 -4
- siliconcompiler/utils/__init__.py +2 -23
- siliconcompiler/utils/flowgraph.py +5 -5
- siliconcompiler/utils/logging.py +2 -1
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.0.dist-info}/METADATA +4 -3
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.0.dist-info}/RECORD +47 -42
- siliconcompiler/scheduler/docker_runner.py +0 -254
- siliconcompiler/schema/journalingschema.py +0 -242
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.0.dist-info}/WHEEL +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.0.dist-info}/entry_points.txt +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.0.dist-info}/licenses/LICENSE +0 -0
- {siliconcompiler-0.33.2.dist-info → siliconcompiler-0.34.0.dist-info}/top_level.txt +0 -0
siliconcompiler/package/git.py
CHANGED
|
@@ -3,82 +3,80 @@ import shutil
|
|
|
3
3
|
import os.path
|
|
4
4
|
|
|
5
5
|
from git import Repo, GitCommandError
|
|
6
|
-
from
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
6
|
+
from siliconcompiler.package import RemoteResolver
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_resolver():
|
|
10
|
+
return {
|
|
11
|
+
"git": GitResolver,
|
|
12
|
+
"git+https": GitResolver,
|
|
13
|
+
"git+ssh": GitResolver,
|
|
14
|
+
"ssh": GitResolver
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GitResolver(RemoteResolver):
|
|
19
|
+
def __init__(self, name, root, source, reference=None):
|
|
20
|
+
super().__init__(name, root, source, reference)
|
|
21
|
+
|
|
22
|
+
def check_cache(self):
|
|
23
|
+
if os.path.exists(self.cache_path):
|
|
24
|
+
try:
|
|
25
|
+
repo = Repo(self.cache_path)
|
|
26
|
+
if repo.untracked_files or repo.index.diff("HEAD"):
|
|
27
|
+
self.logger.warning('The repo of the cached data is dirty.')
|
|
28
|
+
return True
|
|
29
|
+
except GitCommandError:
|
|
30
|
+
self.logger.warning('Deleting corrupted cache data.')
|
|
31
|
+
shutil.rmtree(self.cache_path)
|
|
32
|
+
return False
|
|
33
|
+
return False
|
|
34
|
+
|
|
35
|
+
def __get_token_env(self):
|
|
36
|
+
token_name = self.name.upper()
|
|
37
|
+
for tok in ('#', '$', '&', '-', '=', '!', '/'):
|
|
38
|
+
token_name = token_name.replace(tok, '')
|
|
39
|
+
|
|
40
|
+
search_env = (
|
|
41
|
+
f'GITHUB_{token_name}_TOKEN',
|
|
42
|
+
'GITHUB_TOKEN',
|
|
43
|
+
'GIT_TOKEN'
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
token = None
|
|
47
|
+
for env in search_env:
|
|
48
|
+
token = os.environ.get(env, None)
|
|
49
|
+
|
|
50
|
+
if token:
|
|
51
|
+
return token
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
@property
|
|
55
|
+
def git_path(self):
|
|
56
|
+
if self.urlscheme == "git+ssh":
|
|
57
|
+
return f"ssh://{self.urlpath}{self.urlparse.path}"
|
|
58
|
+
if self.urlscheme == "ssh":
|
|
59
|
+
return self.source
|
|
60
|
+
url = self.urlparse
|
|
61
|
+
if not url.username and self.__get_token_env():
|
|
62
|
+
url = url._replace(netloc=f'{self.__get_token_env()}@{url.hostname}')
|
|
63
|
+
url = url._replace(scheme='https')
|
|
64
|
+
return url.geturl()
|
|
27
65
|
|
|
28
|
-
|
|
66
|
+
def resolve_remote(self):
|
|
29
67
|
try:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def clone_synchronized(chip, package, path, ref, url, data_path):
|
|
47
|
-
try:
|
|
48
|
-
clone_from_git(chip, package, path, ref, url, data_path)
|
|
49
|
-
except GitCommandError as e:
|
|
50
|
-
if 'Permission denied' in repr(e):
|
|
51
|
-
if url.scheme in ['ssh', 'git+ssh']:
|
|
52
|
-
chip.logger.error('Failed to authenticate. Please setup your git ssh.')
|
|
53
|
-
elif url.scheme in ['git', 'git+https']:
|
|
54
|
-
chip.logger.error('Failed to authenticate. Please use a token or ssh.')
|
|
55
|
-
else:
|
|
56
|
-
chip.logger.error(str(e))
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def clone_from_git(chip, package, path, ref, url, data_path):
|
|
60
|
-
if url.scheme in ['git', 'git+https'] and url.username:
|
|
61
|
-
chip.logger.warning('Your token is in the data source path and will be stored in the '
|
|
62
|
-
'schema. If you do not want this set the env variable GIT_TOKEN '
|
|
63
|
-
'or use ssh for authentication.')
|
|
64
|
-
if url.scheme in ['git+ssh']:
|
|
65
|
-
chip.logger.info(f'Cloning {package} data from {url.netloc}:{url.path[1:]}')
|
|
66
|
-
# Git requires the format git@github.com:org/repo instead of git@github.com/org/repo
|
|
67
|
-
repo = Repo.clone_from(f'{url.netloc}/{url.path[1:]}',
|
|
68
|
-
data_path,
|
|
69
|
-
recurse_submodules=True)
|
|
70
|
-
elif url.scheme in ['ssh']:
|
|
71
|
-
chip.logger.info(f'Cloning {package} data from {path}')
|
|
72
|
-
repo = Repo.clone_from(path,
|
|
73
|
-
data_path,
|
|
74
|
-
recurse_submodules=True)
|
|
75
|
-
else:
|
|
76
|
-
if os.environ.get('GIT_TOKEN') and not url.username:
|
|
77
|
-
url = url._replace(netloc=f'{os.environ.get("GIT_TOKEN")}@{url.hostname}')
|
|
78
|
-
url = url._replace(scheme='https')
|
|
79
|
-
chip.logger.info(f'Cloning {package} data from {url.geturl()}')
|
|
80
|
-
repo = Repo.clone_from(url.geturl(), data_path, recurse_submodules=True)
|
|
81
|
-
chip.logger.info(f'Checking out {ref}')
|
|
82
|
-
repo.git.checkout(ref)
|
|
83
|
-
for submodule in repo.submodules:
|
|
84
|
-
submodule.update(recursive=True, init=True, force=True)
|
|
68
|
+
path = self.git_path
|
|
69
|
+
self.logger.info(f'Cloning {self.name} data from {path}')
|
|
70
|
+
repo = Repo.clone_from(path, self.cache_path, recurse_submodules=True)
|
|
71
|
+
self.logger.info(f'Checking out {self.reference}')
|
|
72
|
+
repo.git.checkout(self.reference)
|
|
73
|
+
for submodule in repo.submodules:
|
|
74
|
+
submodule.update(recursive=True, init=True, force=True)
|
|
75
|
+
except GitCommandError as e:
|
|
76
|
+
if 'Permission denied' in repr(e):
|
|
77
|
+
if self.urlscheme in ('ssh', 'git+ssh'):
|
|
78
|
+
raise RuntimeError('Failed to authenticate. Please setup your git ssh.')
|
|
79
|
+
elif self.urlscheme in ('git', 'git+https'):
|
|
80
|
+
raise RuntimeError('Failed to authenticate. Please use a token or ssh.')
|
|
81
|
+
else:
|
|
82
|
+
raise e
|
|
@@ -1,124 +1,97 @@
|
|
|
1
1
|
import os
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
from github import Github, Auth
|
|
4
4
|
from github.GithubException import UnknownObjectException
|
|
5
|
-
from urllib.parse import urlparse
|
|
6
|
-
from siliconcompiler.package import get_download_cache_path
|
|
7
|
-
from siliconcompiler.package import aquire_data_lock, release_data_lock
|
|
8
|
-
from siliconcompiler.package.https import _http_resolver
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def get_resolver(url):
|
|
12
|
-
if url.scheme in ("github",):
|
|
13
|
-
return github_any_resolver
|
|
14
|
-
if url.scheme in ("github+private",):
|
|
15
|
-
return github_private_resolver
|
|
16
|
-
return None
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
def github_any_resolver(chip, package, path, ref, url, fetch):
|
|
20
|
-
data_path, data_path_lock = get_download_cache_path(chip, package, ref)
|
|
21
|
-
|
|
22
|
-
if not fetch:
|
|
23
|
-
return data_path, False
|
|
24
|
-
|
|
25
|
-
# Acquire lock
|
|
26
|
-
data_lock = InterProcessLock(data_path_lock)
|
|
27
|
-
aquire_data_lock(data_path, data_lock)
|
|
28
|
-
|
|
29
|
-
if os.path.exists(data_path):
|
|
30
|
-
release_data_lock(data_lock)
|
|
31
|
-
return data_path, False
|
|
32
|
-
|
|
33
|
-
try:
|
|
34
|
-
return _github_resolver(chip, package, path, ref, url, data_lock)
|
|
35
|
-
except UnknownObjectException:
|
|
36
|
-
return github_private_resolver(chip, package, path, ref, url, fetch, data_lock=data_lock)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def github_private_resolver(chip, package, path, ref, url, fetch, data_lock=None):
|
|
40
|
-
data_path, data_path_lock = get_download_cache_path(chip, package, ref)
|
|
41
|
-
|
|
42
|
-
if not fetch:
|
|
43
|
-
return data_path, False
|
|
44
|
-
|
|
45
|
-
if not data_lock:
|
|
46
|
-
# Acquire lock
|
|
47
|
-
data_lock = InterProcessLock(data_path_lock)
|
|
48
|
-
aquire_data_lock(data_path, data_lock)
|
|
49
5
|
|
|
50
|
-
|
|
51
|
-
release_data_lock(data_lock)
|
|
52
|
-
return data_path, False
|
|
6
|
+
from siliconcompiler.package.https import HTTPResolver
|
|
53
7
|
|
|
54
|
-
gh = Github(auth=Auth.Token(__get_github_auth_token(package)))
|
|
55
8
|
|
|
56
|
-
|
|
9
|
+
def get_resolver():
|
|
10
|
+
return {
|
|
11
|
+
"github": GithubResolver,
|
|
12
|
+
"github+private": GithubResolver
|
|
13
|
+
}
|
|
57
14
|
|
|
58
15
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
16
|
+
class GithubResolver(HTTPResolver):
|
|
17
|
+
def __init__(self, name, root, source, reference=None):
|
|
18
|
+
super().__init__(name, root, source, reference)
|
|
62
19
|
|
|
63
|
-
|
|
20
|
+
if len(self.gh_path) != 4:
|
|
21
|
+
raise ValueError(
|
|
22
|
+
f"{self.source} is not in the proper form: "
|
|
23
|
+
"<owner>/<repository>/<version>/<artifact>")
|
|
64
24
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
25
|
+
@property
|
|
26
|
+
def gh_path(self):
|
|
27
|
+
return self.urlpath, *self.urlparse.path.split("/")[1:]
|
|
68
28
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
29
|
+
@property
|
|
30
|
+
def download_url(self):
|
|
31
|
+
url_parts = self.gh_path
|
|
72
32
|
|
|
73
|
-
|
|
33
|
+
repository = "/".join(url_parts[0:2])
|
|
34
|
+
release = url_parts[2]
|
|
35
|
+
artifact = url_parts[3]
|
|
74
36
|
|
|
75
|
-
|
|
37
|
+
if self.urlscheme == "github+private":
|
|
38
|
+
return self.__get_release_url(repository, release, artifact, True)
|
|
76
39
|
|
|
40
|
+
try:
|
|
41
|
+
return self.__get_release_url(repository, release, artifact, False)
|
|
42
|
+
except UnknownObjectException:
|
|
43
|
+
return self.__get_release_url(repository, release, artifact, True)
|
|
77
44
|
|
|
78
|
-
def __get_release_url(
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
45
|
+
def __get_release_url(self, repository, release, artifact, private: bool):
|
|
46
|
+
if artifact == f"{release}.zip":
|
|
47
|
+
return f"https://github.com/{repository}/archive/refs/tags/{release}.zip"
|
|
48
|
+
if artifact == f"{release}.tar.gz":
|
|
49
|
+
return f"https://github.com/{repository}/archive/refs/tags/{release}.tar.gz"
|
|
83
50
|
|
|
84
|
-
|
|
51
|
+
repo = self.__gh(private).get_repo(repository)
|
|
85
52
|
|
|
86
|
-
|
|
87
|
-
|
|
53
|
+
if not release:
|
|
54
|
+
release = repo.get_latest_release().tag_name
|
|
88
55
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
56
|
+
url = None
|
|
57
|
+
for repo_release in repo.get_releases():
|
|
58
|
+
if repo_release.tag_name == release:
|
|
59
|
+
for asset in repo_release.assets:
|
|
60
|
+
if asset.name == artifact:
|
|
61
|
+
url = asset.url
|
|
95
62
|
|
|
96
|
-
|
|
97
|
-
|
|
63
|
+
if not url:
|
|
64
|
+
raise ValueError(f'Unable to find release asset: {repository}/{release}/{artifact}')
|
|
98
65
|
|
|
99
|
-
|
|
66
|
+
return url
|
|
100
67
|
|
|
68
|
+
def __get_gh_auth(self):
|
|
69
|
+
token_name = self.name.upper()
|
|
70
|
+
for tok in ('#', '$', '&', '-', '=', '!', '/'):
|
|
71
|
+
token_name = token_name.replace(tok, '')
|
|
101
72
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
73
|
+
search_env = (
|
|
74
|
+
f'GITHUB_{token_name}_TOKEN',
|
|
75
|
+
'GITHUB_TOKEN',
|
|
76
|
+
'GIT_TOKEN'
|
|
77
|
+
)
|
|
106
78
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
'GIT_TOKEN'
|
|
111
|
-
)
|
|
79
|
+
token = None
|
|
80
|
+
for env in search_env:
|
|
81
|
+
token = os.environ.get(env, None)
|
|
112
82
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
token = os.environ.get(env, None)
|
|
83
|
+
if token:
|
|
84
|
+
break
|
|
116
85
|
|
|
117
|
-
if token:
|
|
118
|
-
|
|
86
|
+
if not token:
|
|
87
|
+
raise ValueError('Unable to determine authorization token for GitHub, '
|
|
88
|
+
'please set one of the following environmental variables: '
|
|
89
|
+
f'{", ".join(search_env)}')
|
|
119
90
|
|
|
120
|
-
|
|
121
|
-
raise ValueError('Unable to determine authorization token for GitHub, '
|
|
122
|
-
f'please set one of the following environmental variables: {search_env}')
|
|
91
|
+
return token
|
|
123
92
|
|
|
124
|
-
|
|
93
|
+
def __gh(self, private: bool) -> Github:
|
|
94
|
+
if private:
|
|
95
|
+
return Github(auth=Auth.Token(self.__get_gh_auth()))
|
|
96
|
+
else:
|
|
97
|
+
return Github()
|
siliconcompiler/package/https.py
CHANGED
|
@@ -5,99 +5,83 @@ import zipfile
|
|
|
5
5
|
|
|
6
6
|
import os.path
|
|
7
7
|
|
|
8
|
-
from fasteners import InterProcessLock
|
|
9
8
|
from io import BytesIO
|
|
10
9
|
from urllib.parse import urlparse
|
|
11
10
|
|
|
12
|
-
from siliconcompiler import
|
|
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
|
-
gh_ref = gh_ref[0:-4]
|
|
90
|
-
else:
|
|
91
|
-
gh_ref = gh_ref.split('.')[0]
|
|
92
|
-
|
|
93
|
-
if gh_ref.startswith('v'):
|
|
94
|
-
gh_ref = gh_ref[1:]
|
|
95
|
-
|
|
96
|
-
github_folder = f"{repo}-{gh_ref}"
|
|
97
|
-
|
|
98
|
-
if github_folder in os.listdir(data_path):
|
|
99
|
-
# This moves all files one level up
|
|
100
|
-
git_path = os.path.join(data_path, github_folder)
|
|
101
|
-
for data_file in os.listdir(git_path):
|
|
102
|
-
shutil.move(os.path.join(git_path, data_file), data_path)
|
|
103
|
-
os.removedirs(git_path)
|
|
11
|
+
from siliconcompiler.package import RemoteResolver
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def get_resolver():
|
|
15
|
+
return {
|
|
16
|
+
"http": HTTPResolver,
|
|
17
|
+
"https": HTTPResolver
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class HTTPResolver(RemoteResolver):
|
|
22
|
+
def check_cache(self):
|
|
23
|
+
return os.path.exists(self.cache_path)
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def download_url(self):
|
|
27
|
+
data_url = self.source
|
|
28
|
+
if data_url.endswith('/'):
|
|
29
|
+
data_url = f"{data_url}{self.reference}.tar.gz"
|
|
30
|
+
return data_url
|
|
31
|
+
|
|
32
|
+
def resolve_remote(self):
|
|
33
|
+
data_url = self.download_url
|
|
34
|
+
|
|
35
|
+
headers = {}
|
|
36
|
+
auth_token = os.environ.get('GIT_TOKEN', self.urlparse.username)
|
|
37
|
+
if auth_token:
|
|
38
|
+
headers['Authorization'] = f'token {auth_token}'
|
|
39
|
+
if "github" in data_url:
|
|
40
|
+
headers['Accept'] = 'application/octet-stream'
|
|
41
|
+
|
|
42
|
+
self.logger.info(f'Downloading {self.name} data from {data_url}')
|
|
43
|
+
|
|
44
|
+
response = requests.get(data_url, stream=True, headers=headers)
|
|
45
|
+
if not response.ok:
|
|
46
|
+
raise FileNotFoundError(f'Failed to download {self.name} data source.')
|
|
47
|
+
|
|
48
|
+
os.makedirs(self.cache_path, exist_ok=True)
|
|
49
|
+
|
|
50
|
+
fileobj = BytesIO(response.content)
|
|
51
|
+
try:
|
|
52
|
+
with tarfile.open(fileobj=fileobj, mode='r|gz') as tar_ref:
|
|
53
|
+
tar_ref.extractall(path=self.cache_path)
|
|
54
|
+
except tarfile.ReadError:
|
|
55
|
+
fileobj.seek(0)
|
|
56
|
+
# Try as zip
|
|
57
|
+
with zipfile.ZipFile(fileobj) as zip_ref:
|
|
58
|
+
zip_ref.extractall(path=self.cache_path)
|
|
59
|
+
|
|
60
|
+
if 'github' in data_url and len(os.listdir(self.cache_path)) == 1:
|
|
61
|
+
# Github inserts one folder at the highest level of the tar file
|
|
62
|
+
# this compensates for this behavior
|
|
63
|
+
gh_url = urlparse(data_url)
|
|
64
|
+
|
|
65
|
+
repo = gh_url.path.split('/')[2]
|
|
66
|
+
|
|
67
|
+
gh_ref = gh_url.path.split('/')[-1]
|
|
68
|
+
if repo.endswith('.git'):
|
|
69
|
+
gh_ref = self.reference
|
|
70
|
+
elif gh_ref.endswith('.tar.gz'):
|
|
71
|
+
gh_ref = gh_ref[0:-7]
|
|
72
|
+
elif gh_ref.endswith('.tgz'):
|
|
73
|
+
gh_ref = gh_ref[0:-4]
|
|
74
|
+
else:
|
|
75
|
+
gh_ref = gh_ref.split('.')[0]
|
|
76
|
+
|
|
77
|
+
if gh_ref.startswith('v'):
|
|
78
|
+
gh_ref = gh_ref[1:]
|
|
79
|
+
|
|
80
|
+
github_folder = f"{repo}-{gh_ref}"
|
|
81
|
+
|
|
82
|
+
if github_folder in os.listdir(self.cache_path):
|
|
83
|
+
# This moves all files one level up
|
|
84
|
+
git_path = os.path.join(self.cache_path, github_folder)
|
|
85
|
+
for data_file in os.listdir(git_path):
|
|
86
|
+
shutil.move(os.path.join(git_path, data_file), self.cache_path)
|
|
87
|
+
os.removedirs(git_path)
|