pybiolib 1.1.1979__py3-none-any.whl → 1.1.1984__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.
- biolib/_internal/fuse_mount/experiment_fuse_mount.py +65 -60
- {pybiolib-1.1.1979.dist-info → pybiolib-1.1.1984.dist-info}/METADATA +1 -1
- {pybiolib-1.1.1979.dist-info → pybiolib-1.1.1984.dist-info}/RECORD +6 -6
- {pybiolib-1.1.1979.dist-info → pybiolib-1.1.1984.dist-info}/LICENSE +0 -0
- {pybiolib-1.1.1979.dist-info → pybiolib-1.1.1984.dist-info}/WHEEL +0 -0
- {pybiolib-1.1.1979.dist-info → pybiolib-1.1.1984.dist-info}/entry_points.txt +0 -0
@@ -3,12 +3,11 @@ import os
|
|
3
3
|
import stat
|
4
4
|
from datetime import datetime, timezone
|
5
5
|
from time import time
|
6
|
-
from typing import Iterable
|
7
6
|
|
8
7
|
from biolib._internal.libs.fusepy import FUSE, FuseOSError, Operations
|
9
8
|
from biolib.biolib_errors import BioLibError
|
10
9
|
from biolib.jobs import Job
|
11
|
-
from biolib.typing_utils import Dict, Optional, Tuple, TypedDict
|
10
|
+
from biolib.typing_utils import Dict, List, Optional, Tuple, TypedDict
|
12
11
|
|
13
12
|
|
14
13
|
class _AttributeDict(TypedDict):
|
@@ -27,7 +26,6 @@ class ExperimentFuseMount(Operations):
|
|
27
26
|
self._experiment = experiment
|
28
27
|
self._job_names_map: Optional[Dict[str, Job]] = None
|
29
28
|
self._jobs_last_fetched_at: float = 0.0
|
30
|
-
self._root_path: str = '/'
|
31
29
|
self._mounted_at_epoch_seconds: int = int(time())
|
32
30
|
|
33
31
|
@staticmethod
|
@@ -41,80 +39,77 @@ class ExperimentFuseMount(Operations):
|
|
41
39
|
)
|
42
40
|
|
43
41
|
def getattr(self, path: str, fh=None) -> _AttributeDict:
|
44
|
-
|
45
|
-
|
46
|
-
# return folder dir
|
47
|
-
return self._get_folder_attr(timestamp_epoch_seconds=self._mounted_at_epoch_seconds)
|
48
|
-
|
49
|
-
job_name, job_path = self._parse_path(path)
|
50
|
-
job = self._get_job_names_map().get(job_name)
|
51
|
-
if not job:
|
52
|
-
# job not found
|
53
|
-
raise FuseOSError(errno.ENOENT)
|
42
|
+
if path == '/':
|
43
|
+
return self._get_directory_attributes(timestamp_epoch_seconds=self._mounted_at_epoch_seconds)
|
54
44
|
|
45
|
+
job, path_in_job = self._parse_path(path)
|
55
46
|
job_finished_at_epoch_seconds: int = int(
|
56
47
|
datetime.fromisoformat(job.to_dict()['finished_at'].rstrip('Z')).replace(tzinfo=timezone.utc).timestamp()
|
57
48
|
)
|
58
|
-
|
59
|
-
|
60
|
-
return self.
|
49
|
+
|
50
|
+
if path_in_job == '/':
|
51
|
+
return self._get_directory_attributes(timestamp_epoch_seconds=job_finished_at_epoch_seconds)
|
61
52
|
|
62
53
|
try:
|
63
|
-
file = job.get_output_file(
|
54
|
+
file = job.get_output_file(path_in_job)
|
55
|
+
return self._get_file_attributes(
|
56
|
+
timestamp_epoch_seconds=job_finished_at_epoch_seconds,
|
57
|
+
size_in_bytes=file.length,
|
58
|
+
)
|
64
59
|
except BioLibError:
|
65
60
|
# file not found
|
66
|
-
|
61
|
+
pass
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
st_mtime=job_finished_at_epoch_seconds,
|
74
|
-
st_nlink=1,
|
75
|
-
st_size=file.length,
|
76
|
-
st_uid=os.getuid(),
|
77
|
-
)
|
63
|
+
file_paths_in_job = [file.path for file in job.list_output_files()]
|
64
|
+
|
65
|
+
for file_path_in_job in file_paths_in_job:
|
66
|
+
if file_path_in_job.startswith(path_in_job):
|
67
|
+
return self._get_directory_attributes(timestamp_epoch_seconds=job_finished_at_epoch_seconds)
|
78
68
|
|
79
|
-
|
69
|
+
raise FuseOSError(errno.ENOENT) from None # No such file or directory
|
70
|
+
|
71
|
+
def readdir(self, path: str, fh: int) -> List[str]:
|
80
72
|
directory_entries = ['.', '..']
|
73
|
+
|
81
74
|
if path == '/':
|
82
|
-
|
83
|
-
directory_entries.append(name)
|
75
|
+
directory_entries.extend(self._get_job_names_map(refresh_jobs=True).keys())
|
84
76
|
else:
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
77
|
+
job, path_in_job = self._parse_path(path)
|
78
|
+
dir_path_in_job = '/' if path_in_job == '/' else path_in_job + '/'
|
79
|
+
depth = dir_path_in_job.count('/')
|
80
|
+
directory_entries.extend(
|
81
|
+
set(
|
82
|
+
[
|
83
|
+
file.path.split('/')[depth]
|
84
|
+
for file in job.list_output_files()
|
85
|
+
if file.path.startswith(dir_path_in_job)
|
86
|
+
]
|
87
|
+
)
|
89
88
|
)
|
90
89
|
|
91
|
-
|
92
|
-
directory_entries.append(key)
|
93
|
-
|
94
|
-
yield from directory_entries
|
90
|
+
return directory_entries
|
95
91
|
|
96
92
|
def open(self, path: str, flags: int) -> int:
|
97
|
-
|
98
|
-
job = self._get_job_names_map()[job_name]
|
93
|
+
job, path_in_job = self._parse_path(path)
|
99
94
|
try:
|
100
|
-
job.get_output_file(
|
101
|
-
return 0 # return dummy file handle
|
95
|
+
job.get_output_file(path_in_job)
|
102
96
|
except BioLibError:
|
103
97
|
# file not found
|
104
98
|
raise FuseOSError(errno.ENOENT) from None
|
105
99
|
|
100
|
+
return 0 # return dummy file handle
|
101
|
+
|
106
102
|
def read(self, path: str, size: int, offset: int, fh: int) -> bytes:
|
107
|
-
|
108
|
-
job = self._get_job_names_map()[job_name]
|
103
|
+
job, path_in_job = self._parse_path(path)
|
109
104
|
try:
|
110
|
-
file = job.get_output_file(
|
105
|
+
file = job.get_output_file(path_in_job)
|
111
106
|
except BioLibError:
|
112
|
-
# file
|
113
|
-
raise FuseOSError(errno.ENOENT) from None
|
107
|
+
raise FuseOSError(errno.ENOENT) from None # No such file or directory
|
114
108
|
|
115
109
|
return file.get_data(start=offset, length=size)
|
116
110
|
|
117
|
-
|
111
|
+
@staticmethod
|
112
|
+
def _get_directory_attributes(timestamp_epoch_seconds: int) -> _AttributeDict:
|
118
113
|
return _AttributeDict(
|
119
114
|
st_atime=timestamp_epoch_seconds,
|
120
115
|
st_ctime=timestamp_epoch_seconds,
|
@@ -126,6 +121,19 @@ class ExperimentFuseMount(Operations):
|
|
126
121
|
st_uid=os.getuid(),
|
127
122
|
)
|
128
123
|
|
124
|
+
@staticmethod
|
125
|
+
def _get_file_attributes(timestamp_epoch_seconds: int, size_in_bytes: int) -> _AttributeDict:
|
126
|
+
return _AttributeDict(
|
127
|
+
st_atime=timestamp_epoch_seconds,
|
128
|
+
st_ctime=timestamp_epoch_seconds,
|
129
|
+
st_gid=os.getgid(),
|
130
|
+
st_mode=stat.S_IFREG | 0o444, # Regular file with read permissions for owner, group, and others.
|
131
|
+
st_mtime=timestamp_epoch_seconds,
|
132
|
+
st_nlink=1,
|
133
|
+
st_size=size_in_bytes,
|
134
|
+
st_uid=os.getuid(),
|
135
|
+
)
|
136
|
+
|
129
137
|
def _get_job_names_map(self, refresh_jobs=False) -> Dict[str, Job]:
|
130
138
|
current_time = time()
|
131
139
|
if not self._job_names_map or (current_time - self._jobs_last_fetched_at > 1 and refresh_jobs):
|
@@ -134,18 +142,15 @@ class ExperimentFuseMount(Operations):
|
|
134
142
|
|
135
143
|
return self._job_names_map
|
136
144
|
|
137
|
-
def
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
145
|
+
def _parse_path(self, path: str) -> Tuple[Job, str]:
|
146
|
+
path_splitted = path.split('/')
|
147
|
+
job_name = path_splitted[1]
|
148
|
+
path_in_job = '/' + '/'.join(path_splitted[2:])
|
149
|
+
job = self._get_job_names_map().get(job_name)
|
150
|
+
if not job:
|
151
|
+
raise FuseOSError(errno.ENOENT) # No such file or directory
|
142
152
|
|
143
|
-
|
144
|
-
full_path = self._full_path(path)
|
145
|
-
full_path_splitted = full_path.split('/')
|
146
|
-
job_name = full_path_splitted[1]
|
147
|
-
job_path = '/'.join(full_path_splitted[2:])
|
148
|
-
return job_name, job_path
|
153
|
+
return job, path_in_job
|
149
154
|
|
150
155
|
# ----------------------------------- File system methods not implemented below -----------------------------------
|
151
156
|
|
@@ -6,7 +6,7 @@ biolib/_internal/data_record/__init__.py,sha256=1Bk303i3rFet9veS56fIsrBYtT5X3n9v
|
|
6
6
|
biolib/_internal/data_record/data_record.py,sha256=ctijrrZ-LfUxtwzS8PEVa1VBuBLVWEhmo2yHcEDkC0A,7178
|
7
7
|
biolib/_internal/data_record/remote_storage_endpoint.py,sha256=LPq8Lr5FhKF9_o5K-bUdT7TeLe5XFUD0AAeTkNEVZug,1133
|
8
8
|
biolib/_internal/fuse_mount/__init__.py,sha256=B_tM6RM2dBw-vbpoHJC4X3tOAaN1H2RDvqYJOw3xFwg,55
|
9
|
-
biolib/_internal/fuse_mount/experiment_fuse_mount.py,sha256=
|
9
|
+
biolib/_internal/fuse_mount/experiment_fuse_mount.py,sha256=DcR2NyUyZYgpsaKM1WBJZChAaD2vvt_vvZCXj-P2UTs,6878
|
10
10
|
biolib/_internal/http_client.py,sha256=DdooXei93JKGYGV4aQmzue_oFzvHkozg2UCxgk9dfDM,5081
|
11
11
|
biolib/_internal/libs/__init__.py,sha256=Jdf4tNPqe_oIIf6zYml6TiqhL_02Vyqwge6IELrAFhw,98
|
12
12
|
biolib/_internal/libs/fusepy/__init__.py,sha256=AWDzNFS-XV_5yKb0Qx7kggIhPzq1nj_BZS5y2Nso08k,41944
|
@@ -109,8 +109,8 @@ biolib/utils/cache_state.py,sha256=u256F37QSRIVwqKlbnCyzAX4EMI-kl6Dwu6qwj-Qmag,3
|
|
109
109
|
biolib/utils/multipart_uploader.py,sha256=XvGP1I8tQuKhAH-QugPRoEsCi9qvbRk-DVBs5PNwwJo,8452
|
110
110
|
biolib/utils/seq_util.py,sha256=jC5WhH63FTD7SLFJbxQGA2hOt9NTwq9zHl_BEec1Z0c,4907
|
111
111
|
biolib/utils/zip/remote_zip.py,sha256=0wErYlxir5921agfFeV1xVjf29l9VNgGQvNlWOlj2Yc,23232
|
112
|
-
pybiolib-1.1.
|
113
|
-
pybiolib-1.1.
|
114
|
-
pybiolib-1.1.
|
115
|
-
pybiolib-1.1.
|
116
|
-
pybiolib-1.1.
|
112
|
+
pybiolib-1.1.1984.dist-info/LICENSE,sha256=F2h7gf8i0agDIeWoBPXDMYScvQOz02pAWkKhTGOHaaw,1067
|
113
|
+
pybiolib-1.1.1984.dist-info/METADATA,sha256=PO0Sif5QkYXg1P20p7306bX-CXn6-Mpee7epEsP-1Fo,1508
|
114
|
+
pybiolib-1.1.1984.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
115
|
+
pybiolib-1.1.1984.dist-info/entry_points.txt,sha256=p6DyaP_2kctxegTX23WBznnrDi4mz6gx04O5uKtRDXg,42
|
116
|
+
pybiolib-1.1.1984.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|