pybiolib 1.2.1304__py3-none-any.whl → 1.2.1310__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.

Potentially problematic release.


This version of pybiolib might be problematic. Click here for more details.

@@ -21,7 +21,7 @@ from biolib.biolib_api_client.biolib_app_api import BiolibAppApi
21
21
  from biolib.biolib_docker_client import BiolibDockerClient
22
22
  from biolib.biolib_errors import BioLibError
23
23
  from biolib.biolib_logging import logger
24
- from biolib.typing_utils import Iterable, Optional, Set, TypedDict
24
+ from biolib.typing_utils import Dict, Iterable, Optional, Set, TypedDict
25
25
  from biolib.utils.app_uri import parse_app_uri
26
26
 
27
27
  REGEX_MARKDOWN_INLINE_IMAGE = re.compile(r'!\[(?P<alt>.*)\]\((?P<src>.*)\)')
@@ -109,8 +109,10 @@ def _process_docker_status_updates_with_progress_bar(status_updates: Iterable[Do
109
109
 
110
110
 
111
111
  def _process_docker_status_updates_with_logging(status_updates: Iterable[DockerStatusUpdate], action: str) -> None:
112
- layer_progress = {}
113
- layer_status = {}
112
+ layer_progress: Dict[str, float] = {}
113
+ layer_status: Dict[str, str] = {}
114
+ layer_details: Dict[str, Dict[str, int]] = {}
115
+ layer_bytes_at_last_log: Dict[str, int] = {}
114
116
  last_log_time = time.time()
115
117
 
116
118
  logger.info(f'{action} Docker image...')
@@ -128,6 +130,7 @@ def _process_docker_status_updates_with_logging(status_updates: Iterable[DockerS
128
130
  percentage = (current / total * 100) if total > 0 else 0
129
131
  layer_progress[layer_id] = percentage
130
132
  layer_status[layer_id] = f'{action.lower()}'
133
+ layer_details[layer_id] = {'current': current, 'total': total}
131
134
  elif update.get('status') == 'Layer already exists':
132
135
  layer_progress[layer_id] = 100
133
136
  layer_status[layer_id] = 'already exists'
@@ -146,16 +149,33 @@ def _process_docker_status_updates_with_logging(status_updates: Iterable[DockerS
146
149
  logger.info(f'{action} Docker image - {status}')
147
150
 
148
151
  if current_time - last_log_time >= 10.0:
149
- _log_progress_summary(action, layer_progress, layer_status)
152
+ _log_progress_summary(
153
+ action,
154
+ layer_progress,
155
+ layer_status,
156
+ layer_details,
157
+ layer_bytes_at_last_log,
158
+ current_time - last_log_time,
159
+ )
160
+ layer_bytes_at_last_log = {lid: details['current'] for lid, details in layer_details.items()}
150
161
  last_log_time = current_time
151
162
 
152
- _log_progress_summary(action, layer_progress, layer_status)
163
+ _log_progress_summary(
164
+ action, layer_progress, layer_status, layer_details, layer_bytes_at_last_log, time.time() - last_log_time
165
+ )
153
166
  if action == 'Pushing':
154
167
  logger.info('Pushing final image manifest...')
155
168
  logger.info(f'{action} Docker image completed')
156
169
 
157
170
 
158
- def _log_progress_summary(action: str, layer_progress: dict, layer_status: dict) -> None:
171
+ def _log_progress_summary(
172
+ action: str,
173
+ layer_progress: Dict[str, float],
174
+ layer_status: Dict[str, str],
175
+ layer_details: Dict[str, Dict[str, int]],
176
+ layer_bytes_at_last_log: Dict[str, int],
177
+ time_delta: float,
178
+ ) -> None:
159
179
  if not layer_progress and not layer_status:
160
180
  return
161
181
 
@@ -174,7 +194,36 @@ def _log_progress_summary(action: str, layer_progress: dict, layer_status: dict)
174
194
  if status in ['preparing', 'waiting', 'pushing', 'uploading'] and layer_progress.get(layer_id, 0) < 100
175
195
  ]
176
196
 
177
- if active_layers:
197
+ if active_layers and layer_details:
198
+ total_bytes_transferred = 0
199
+ layer_info_parts = []
200
+
201
+ for layer_id in active_layers[:5]:
202
+ if layer_id in layer_details:
203
+ details = layer_details[layer_id]
204
+ current = details['current']
205
+ total = details['total']
206
+ percentage = layer_progress.get(layer_id, 0)
207
+
208
+ bytes_since_last = current - layer_bytes_at_last_log.get(layer_id, 0)
209
+ total_bytes_transferred += bytes_since_last
210
+
211
+ current_mb = current / (1024 * 1024)
212
+ total_mb = total / (1024 * 1024)
213
+ layer_info_parts.append(f'{layer_id}: {current_mb:.1f}/{total_mb:.1f} MB ({percentage:.1f}%)')
214
+
215
+ speed_info = ''
216
+ if time_delta > 0 and total_bytes_transferred > 0:
217
+ speed_mbps = (total_bytes_transferred / (1024 * 1024)) / time_delta
218
+ speed_info = f' @ {speed_mbps:.2f} MB/s'
219
+
220
+ more_layers_info = ''
221
+ if len(active_layers) > 5:
222
+ more_layers_info = f' (+ {len(active_layers) - 5} more)'
223
+
224
+ if layer_info_parts:
225
+ logger.info(f'Active layers: {", ".join(layer_info_parts)}{speed_info}{more_layers_info}')
226
+ elif active_layers:
178
227
  logger.info(f'Active layers: {", ".join(active_layers[:5])}{"..." if len(active_layers) > 5 else ""}')
179
228
 
180
229
 
biolib/jobs/job.py CHANGED
@@ -498,11 +498,11 @@ class Result:
498
498
  stdout_and_stderr_package = base64.b64decode(stdout_and_stderr_package_b64)
499
499
  stdout_and_stderr = StdoutAndStderr(stdout_and_stderr_package).deserialize()
500
500
 
501
- sys.stdout.write(stdout_and_stderr.decode())
501
+ sys.stdout.buffer.write(stdout_and_stderr)
502
502
  if not IS_RUNNING_IN_NOTEBOOK: # for some reason flushing in jupyter notebooks breaks \r handling
503
- sys.stdout.flush()
503
+ sys.stdout.buffer.flush()
504
504
  # flush after having processed all packages
505
- sys.stdout.flush()
505
+ sys.stdout.buffer.flush()
506
506
 
507
507
  def show(self) -> None:
508
508
  self._refetch_job_dict()
@@ -522,11 +522,11 @@ class Result:
522
522
  logger.info(f'--- The result {self.id} has already completed (no streaming will take place) ---')
523
523
  logger.info('--- The stdout log is printed below: ---')
524
524
  sys.stdout.flush()
525
- print(self.get_stdout().decode(), file=sys.stdout)
526
- sys.stdout.flush()
525
+ sys.stdout.buffer.write(self.get_stdout())
526
+ sys.stdout.buffer.flush()
527
527
  logger.info('--- The stderr log is printed below: ---')
528
- print(self.get_stderr().decode(), file=sys.stderr)
529
- sys.stderr.flush()
528
+ sys.stderr.buffer.write(self.get_stderr())
529
+ sys.stderr.buffer.flush()
530
530
  logger.info(f'--- The job {self.id} has already completed. Its output was printed above. ---')
531
531
  return
532
532
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pybiolib
3
- Version: 1.2.1304
3
+ Version: 1.2.1310
4
4
  Summary: BioLib Python Client
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -16,7 +16,7 @@ biolib/_internal/lfs/__init__.py,sha256=gSWo_xg61UniYgD7yNYxeT4I9uaXBCBSi3_nmZjn
16
16
  biolib/_internal/lfs/cache.py,sha256=pQS2np21rdJ6I3DpoOutnzPHpLOZgUIS8TMltUJk_k4,2226
17
17
  biolib/_internal/libs/__init__.py,sha256=Jdf4tNPqe_oIIf6zYml6TiqhL_02Vyqwge6IELrAFhw,98
18
18
  biolib/_internal/libs/fusepy/__init__.py,sha256=AWDzNFS-XV_5yKb0Qx7kggIhPzq1nj_BZS5y2Nso08k,41944
19
- biolib/_internal/push_application.py,sha256=Ljv7cFeaWRlMdHwn93lhooD227_ZvG8oIRTWHdDdB2M,19177
19
+ biolib/_internal/push_application.py,sha256=CzZTInul84L4fGh63P-wQwOMc3UsunECHRx-Mf1jun4,21153
20
20
  biolib/_internal/runtime.py,sha256=srQo9nbmbNI15eZtb2Dea5f2MWBiNMVW6tDUVr7wiPM,517
21
21
  biolib/_internal/string_utils.py,sha256=N7J7oGu6_yA_z0pOiKqxEh__lRdiDLh6kigeDkQEZ5g,265
22
22
  biolib/_internal/templates/__init__.py,sha256=NVbhLUMC8HITzkLvP88Qu7FHaL-SvQord-DX3gh1Ykk,24
@@ -142,7 +142,7 @@ biolib/compute_node/webserver/worker_thread.py,sha256=7uD9yQPhePYvP2HCJ27EeZ_h6p
142
142
  biolib/experiments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
143
143
  biolib/experiments/experiment.py,sha256=4g1xMYmfp5yzSOdwjf3pUUULF9QjqBJb4uQ25FHrFrk,13688
144
144
  biolib/jobs/__init__.py,sha256=aIb2H2DHjQbM2Bs-dysFijhwFcL58Blp0Co0gimED3w,32
145
- biolib/jobs/job.py,sha256=aC3MfyNOC3z1HEK60OASjaS23Bwq0z6Wkjty56JFj7o,29065
145
+ biolib/jobs/job.py,sha256=-yF9JnHH0CEJIqp3qV9Dsv8AwBi_H1alqcKwhh3AORI,29075
146
146
  biolib/jobs/job_result.py,sha256=_xqQu9z9BqPQrU6tjqKPuKlQDt5W0Zw5xiQvzEBkDyE,5266
147
147
  biolib/jobs/types.py,sha256=rFs6bQWsNI-nb1Hu9QzOW2zFZ8bOVt7ax4UpGVASxVA,1034
148
148
  biolib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -158,8 +158,8 @@ biolib/utils/cache_state.py,sha256=u256F37QSRIVwqKlbnCyzAX4EMI-kl6Dwu6qwj-Qmag,3
158
158
  biolib/utils/multipart_uploader.py,sha256=XvGP1I8tQuKhAH-QugPRoEsCi9qvbRk-DVBs5PNwwJo,8452
159
159
  biolib/utils/seq_util.py,sha256=rImaghQGuIqTVWks6b9P2yKuN34uePUYPUFW_Wyoa4A,6737
160
160
  biolib/utils/zip/remote_zip.py,sha256=0wErYlxir5921agfFeV1xVjf29l9VNgGQvNlWOlj2Yc,23232
161
- pybiolib-1.2.1304.dist-info/METADATA,sha256=9hWDP_mnzSSpALZigTvNoptUNQcEbYdCiasZlR8z4a8,1644
162
- pybiolib-1.2.1304.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
163
- pybiolib-1.2.1304.dist-info/entry_points.txt,sha256=p6DyaP_2kctxegTX23WBznnrDi4mz6gx04O5uKtRDXg,42
164
- pybiolib-1.2.1304.dist-info/licenses/LICENSE,sha256=F2h7gf8i0agDIeWoBPXDMYScvQOz02pAWkKhTGOHaaw,1067
165
- pybiolib-1.2.1304.dist-info/RECORD,,
161
+ pybiolib-1.2.1310.dist-info/METADATA,sha256=LNNxEg6rvoh17x8AIKHxVEHRW5CsI2k_Ybi3VrT_o6o,1644
162
+ pybiolib-1.2.1310.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
163
+ pybiolib-1.2.1310.dist-info/entry_points.txt,sha256=p6DyaP_2kctxegTX23WBznnrDi4mz6gx04O5uKtRDXg,42
164
+ pybiolib-1.2.1310.dist-info/licenses/LICENSE,sha256=F2h7gf8i0agDIeWoBPXDMYScvQOz02pAWkKhTGOHaaw,1067
165
+ pybiolib-1.2.1310.dist-info/RECORD,,