code-loader 1.0.151.dev3__tar.gz → 1.0.152.dev1__tar.gz

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.
Files changed (36) hide show
  1. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/PKG-INFO +1 -1
  2. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/datasetclasses.py +9 -3
  3. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/inner_leap_binder/leapbinder_decorators.py +238 -42
  4. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/leaploader.py +7 -7
  5. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/leaploaderbase.py +3 -3
  6. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/pyproject.toml +1 -1
  7. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/LICENSE +0 -0
  8. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/README.md +0 -0
  9. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/__init__.py +0 -0
  10. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/__init__.py +0 -0
  11. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/enums.py +0 -0
  12. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/exceptions.py +0 -0
  13. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/mapping.py +0 -0
  14. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/responsedataclasses.py +0 -0
  15. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/contract/visualizer_classes.py +0 -0
  16. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/default_losses.py +0 -0
  17. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/default_metrics.py +0 -0
  18. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/__init__.py +0 -0
  19. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/api.py +0 -0
  20. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/cli_config_utils.py +0 -0
  21. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/client.py +0 -0
  22. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/epoch.py +0 -0
  23. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/experiment.py +0 -0
  24. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/experiment_context.py +0 -0
  25. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/types.py +0 -0
  26. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/utils.py +0 -0
  27. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
  28. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/inner_leap_binder/__init__.py +0 -0
  29. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/inner_leap_binder/leapbinder.py +0 -0
  30. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/mixpanel_tracker.py +0 -0
  31. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/plot_functions/__init__.py +0 -0
  32. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/plot_functions/plot_functions.py +0 -0
  33. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/plot_functions/visualize.py +0 -0
  34. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/utils.py +0 -0
  35. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/visualizers/__init__.py +0 -0
  36. {code_loader-1.0.151.dev3 → code_loader-1.0.152.dev1}/code_loader/visualizers/default_visualizers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: code-loader
3
- Version: 1.0.151.dev3
3
+ Version: 1.0.152.dev1
4
4
  Summary:
5
5
  Home-page: https://github.com/tensorleap/code-loader
6
6
  License: MIT
@@ -60,9 +60,14 @@ class PreprocessResponse:
60
60
  raise Exception("length is deprecated, please use sample_ids instead.")
61
61
 
62
62
  if self.state is None:
63
- warnings.warn(
64
- "PreprocessResponse.state is not set. For best practice, assign a unique `state` value to each PreprocessResponse instance."
63
+ from code_loader.inner_leap_binder.leapbinder_decorators import store_warning_by_param
64
+ store_warning_by_param(
65
+ param_name="PreprocessResponse.state",
66
+ user_func_name="tensorleap_preprocess",
67
+ default_value=str("specific order"),
68
+ link_to_docs="https://docs.tensorleap.ai/tensorleap-integration/writing-integration-code/preprocess-function",
65
69
  )
70
+
66
71
  else:
67
72
  assert isinstance(self.state, DataStateType), f"PreprocessResponse.state must be of type {DataStateType.__name__} but got {type(self.state)}"
68
73
 
@@ -229,7 +234,8 @@ class CustomLatentSpaceHandler:
229
234
  class PredictionTypeHandler:
230
235
  name: str
231
236
  labels: List[str]
232
- channel_dim: int = -1
237
+ channel_dim: int = "default_value"
238
+
233
239
 
234
240
 
235
241
  @dataclass
@@ -6,7 +6,7 @@ from collections import defaultdict
6
6
  from functools import lru_cache
7
7
  from pathlib import Path
8
8
  from typing import Optional, Union, Callable, List, Dict, Set, Any
9
- from typing import Optional, Union, Callable, List, Dict, get_args, get_origin
9
+ from typing import Optional, Union, Callable, List, Dict, get_args, get_origin, DefaultDict
10
10
 
11
11
  import numpy as np
12
12
  import numpy.typing as npt
@@ -28,11 +28,63 @@ from code_loader.mixpanel_tracker import clear_integration_events, AnalyticsEven
28
28
 
29
29
  import inspect
30
30
  import functools
31
+ import __main__
32
+ from pathlib import Path
31
33
 
32
34
  _called_from_inside_tl_decorator = 0
33
35
  _called_from_inside_tl_integration_test_decorator = False
34
36
  _call_from_tl_platform = os.environ.get('IS_TENSORLEAP_PLATFORM') == 'true'
35
37
 
38
+ # ---- warnings store (module-level) ----
39
+ _UNSET = object()
40
+ _STORED_WARNINGS: List[Dict[str, Any]] = []
41
+ _STORED_WARNING_KEYS: Set[tuple] = set()
42
+ # param_name -> set(user_func_name)
43
+ _PARAM_DEFAULT_FUNCS: DefaultDict[str, Set[str]] = defaultdict(set)
44
+ # param_name -> default_value used (repr-able)
45
+ _PARAM_DEFAULT_VALUE: Dict[str, Any] = {}
46
+ _PARAM_DEFAULT_DOCS: Dict[str, str] = {}
47
+
48
+
49
+ def get_entry_script_path() -> str:
50
+ return getattr(__main__, "__file__", "") or ""
51
+
52
+
53
+ def started_from(filename: str) -> bool:
54
+ entry = get_entry_script_path()
55
+ return bool(entry) and Path(entry).name == filename
56
+
57
+
58
+ def store_warning_by_param(
59
+ *,
60
+ param_name: str,
61
+ user_func_name: str,
62
+ default_value: Any,
63
+ link_to_docs: str = None,
64
+ ) -> None:
65
+ _PARAM_DEFAULT_FUNCS[param_name].add(user_func_name)
66
+
67
+ if param_name not in _PARAM_DEFAULT_VALUE:
68
+ _PARAM_DEFAULT_VALUE[param_name] = default_value
69
+
70
+ if link_to_docs and param_name not in _PARAM_DEFAULT_DOCS:
71
+ _PARAM_DEFAULT_DOCS[param_name] = link_to_docs
72
+
73
+
74
+ def _get_param_default_warnings() -> Dict[str, Dict[str, Any]]:
75
+ out: Dict[str, Dict[str, Any]] = {}
76
+ for p, funcs in _PARAM_DEFAULT_FUNCS.items():
77
+ out[p] = {
78
+ "default_value": _PARAM_DEFAULT_VALUE.get(p, None),
79
+ "funcs": set(funcs),
80
+ "link_to_docs": _PARAM_DEFAULT_DOCS.get(p),
81
+ }
82
+ return out
83
+
84
+
85
+ def _get_stored_warnings() -> List[Dict[str, Any]]:
86
+ return list(_STORED_WARNINGS)
87
+
36
88
 
37
89
  def validate_args_structure(*args, types_order, func_name, expected_names, **kwargs):
38
90
  def _type_to_str(t):
@@ -173,6 +225,8 @@ def tensorleap_integration_test():
173
225
  )
174
226
 
175
227
  def inner(*args, **kwargs):
228
+ if not _call_from_tl_platform:
229
+ set_current('tensorleap_integration_test')
176
230
  validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
177
231
  func_name='integration_test', expected_names=["idx", "preprocess"], **kwargs)
178
232
  _validate_input_args(*args, **kwargs)
@@ -228,7 +282,18 @@ def _safe_get_item(key):
228
282
  raise Exception(f'Tensorleap currently supports models with no more then 10 inputs')
229
283
 
230
284
 
231
- def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]] = []):
285
+ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]] = _UNSET):
286
+ prediction_types_was_provided = prediction_types is not _UNSET
287
+
288
+ if not prediction_types_was_provided:
289
+ prediction_types = []
290
+ if not _call_from_tl_platform:
291
+ store_warning_by_param(
292
+ param_name="prediction_types",
293
+ user_func_name="tensorleap_load_model",
294
+ default_value=prediction_types,
295
+ link_to_docs="https://docs.tensorleap.ai/tensorleap-integration/integration-test#tensorleap_load_model"
296
+ )
232
297
  assert isinstance(prediction_types, list), (
233
298
  f"tensorleap_load_model validation failed: "
234
299
  f" prediction_types is an optional argument of type List[PredictionTypeHandler]] but got {type(prediction_types).__name__}."
@@ -236,6 +301,16 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
236
301
  for i, prediction_type in enumerate(prediction_types):
237
302
  assert isinstance(prediction_type, PredictionTypeHandler), (f"tensorleap_load_model validation failed: "
238
303
  f" prediction_types at position {i} must be of type PredictionTypeHandler but got {type(prediction_types[i]).__name__}.")
304
+ prediction_type_channel_dim_was_provided = prediction_type.channel_dim != "default_value"
305
+ if not prediction_type_channel_dim_was_provided:
306
+ prediction_types[i].channel_dim = -1
307
+ if not _call_from_tl_platform:
308
+ store_warning_by_param(
309
+ param_name=f"prediction_types[{i}].channel_dim",
310
+ user_func_name="tensorleap_load_model",
311
+ default_value=prediction_types[i].channel_dim,
312
+ link_to_docs="https://docs.tensorleap.ai/tensorleap-integration/integration-test#tensorleap_load_model"
313
+ )
239
314
  leap_binder.add_prediction(prediction_type.name, prediction_type.labels, prediction_type.channel_dim, i)
240
315
 
241
316
  def _validate_result(result) -> None:
@@ -274,6 +349,8 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
274
349
 
275
350
  @lru_cache()
276
351
  def inner(*args, **kwargs):
352
+ if not _call_from_tl_platform:
353
+ set_current('tensorleap_load_model')
277
354
  validate_args_structure(*args, types_order=[],
278
355
  func_name='tensorleap_load_model', expected_names=[], **kwargs)
279
356
 
@@ -437,7 +514,7 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
437
514
 
438
515
 
439
516
  def tensorleap_custom_metric(name: str,
440
- direction: Union[MetricDirection, Dict[str, MetricDirection]] = MetricDirection.Downward,
517
+ direction: Union[MetricDirection, Dict[str, MetricDirection]] = _UNSET,
441
518
  compute_insights: Optional[Union[bool, Dict[str, bool]]] = None,
442
519
  connects_to=None):
443
520
  name_to_unique_name = defaultdict(set)
@@ -445,6 +522,20 @@ def tensorleap_custom_metric(name: str,
445
522
  def decorating_function(
446
523
  user_function: Union[CustomCallableInterfaceMultiArgs, CustomMultipleReturnCallableInterfaceMultiArgs,
447
524
  ConfusionMatrixCallableInterfaceMultiArgs]):
525
+ nonlocal direction
526
+
527
+ direction_was_provided = direction is not _UNSET
528
+
529
+ if not direction_was_provided:
530
+ direction = MetricDirection.Downward
531
+ if not _call_from_tl_platform:
532
+ store_warning_by_param(
533
+ param_name="direction",
534
+ user_func_name=user_function.__name__,
535
+ default_value=direction,
536
+ link_to_docs="https://docs.tensorleap.ai/tensorleap-integration/writing-integration-code/custom-metrics"
537
+
538
+ )
448
539
 
449
540
  def _validate_decorators_signature():
450
541
  err_message = f"{user_function.__name__} validation failed.\n"
@@ -637,6 +728,8 @@ def tensorleap_custom_metric(name: str,
637
728
  _add_mapping_connections(connects_to, arg_names, NodeMappingType.Metric, name)
638
729
 
639
730
  def inner(*args, **kwargs):
731
+ if not _call_from_tl_platform:
732
+ set_current('tensorleap_custom_metric')
640
733
  _validate_input_args(*args, **kwargs)
641
734
 
642
735
  result = inner_without_validate(*args, **kwargs)
@@ -686,7 +779,6 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
686
779
  assert isinstance(visualizer_type, LeapDataType), (f"{user_function.__name__} validation failed: "
687
780
  f"visualizer_type should be of type {LeapDataType.__name__} but got {type(visualizer_type)}"
688
781
  )
689
-
690
782
  for viz_handler in leap_binder.setup_container.visualizers:
691
783
  if viz_handler.visualizer_handler_data.name == name:
692
784
  raise Exception(f'Visualizer with name {name} already exists. '
@@ -759,6 +851,8 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
759
851
  _add_mapping_connections(connects_to, arg_names, NodeMappingType.Visualizer, name)
760
852
 
761
853
  def inner(*args, **kwargs):
854
+ if not _call_from_tl_platform:
855
+ set_current('tensorleap_custom_visualizer')
762
856
  _validate_input_args(*args, **kwargs)
763
857
 
764
858
  result = inner_without_validate(*args, **kwargs)
@@ -844,6 +938,8 @@ def tensorleap_metadata(
844
938
  leap_binder.set_metadata(inner_without_validate, name, metadata_type)
845
939
 
846
940
  def inner(*args, **kwargs):
941
+ if not _call_from_tl_platform:
942
+ set_current('tensorleap_metadata')
847
943
  if os.environ.get(mapping_runtime_mode_env_var_mame):
848
944
  return None
849
945
  validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
@@ -937,6 +1033,8 @@ def tensorleap_preprocess():
937
1033
  f'The return list should not contain duplicate PreprocessResponse objects.')
938
1034
 
939
1035
  def inner(*args, **kwargs):
1036
+ if not _call_from_tl_platform:
1037
+ set_current('tensorleap_metadata')
940
1038
  if os.environ.get(mapping_runtime_mode_env_var_mame):
941
1039
  return [None, None, None, None]
942
1040
 
@@ -1145,12 +1243,27 @@ def tensorleap_instances_length_encoder(name: str):
1145
1243
  return decorating_function
1146
1244
 
1147
1245
 
1148
- def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1246
+ def tensorleap_input_encoder(name: str, channel_dim=_UNSET, model_input_index=None):
1149
1247
  def decorating_function(user_function: SectionCallableInterface):
1150
1248
  for input_handler in leap_binder.setup_container.inputs:
1151
1249
  if input_handler.name == name:
1152
1250
  raise Exception(f'Input with name {name} already exists. '
1153
1251
  f'Please choose another')
1252
+ nonlocal channel_dim
1253
+
1254
+ channel_dim_was_provided = channel_dim is not _UNSET
1255
+
1256
+ if not channel_dim_was_provided:
1257
+ channel_dim = -1
1258
+ if not _call_from_tl_platform:
1259
+ store_warning_by_param(
1260
+ param_name="channel_dim",
1261
+ user_func_name=user_function.__name__,
1262
+ default_value=channel_dim,
1263
+ link_to_docs="https://docs.tensorleap.ai/tensorleap-integration/writing-integration-code/input-encoder"
1264
+
1265
+ )
1266
+
1154
1267
  if channel_dim <= 0 and channel_dim != -1:
1155
1268
  raise Exception(f"Channel dim for input {name} is expected to be either -1 or positive")
1156
1269
 
@@ -1185,6 +1298,8 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1185
1298
  leap_binder.set_input(inner_without_validate, name, channel_dim=channel_dim)
1186
1299
 
1187
1300
  def inner(*args, **kwargs):
1301
+ if not _call_from_tl_platform:
1302
+ set_current("tensorleap_input_encoder")
1188
1303
  validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
1189
1304
  func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
1190
1305
  sample_id, preprocess_response = args if len(args) != 0 else kwargs.values()
@@ -1278,6 +1393,8 @@ def tensorleap_gt_encoder(name: str):
1278
1393
  leap_binder.set_ground_truth(inner_without_validate, name)
1279
1394
 
1280
1395
  def inner(*args, **kwargs):
1396
+ if not _call_from_tl_platform:
1397
+ set_current("tensorleap_gt_encoder")
1281
1398
  validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
1282
1399
  func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
1283
1400
  sample_id, preprocess_response = args
@@ -1385,6 +1502,8 @@ def tensorleap_custom_loss(name: str, connects_to=None):
1385
1502
  _add_mapping_connections(connects_to, arg_names, NodeMappingType.CustomLoss, name)
1386
1503
 
1387
1504
  def inner(*args, **kwargs):
1505
+ if not _call_from_tl_platform:
1506
+ set_current("tensorleap_custom_loss")
1388
1507
  _validate_input_args(*args, **kwargs)
1389
1508
 
1390
1509
  result = inner_without_validate(*args, **kwargs)
@@ -1452,47 +1571,97 @@ def tensorleap_custom_layer(name: str):
1452
1571
 
1453
1572
 
1454
1573
  def tensorleap_status_table():
1455
- '''
1456
- Usage example:
1457
- ###################
1458
- leap_integration.py
1459
- ###################
1460
- from code_loader.inner_leap_binder.leapbinder_decorators import tensorleap_status_table
1461
- ...
1462
- ...
1463
- ...
1464
- if __name__ == '__main__':
1465
- tensorleap_status_table()
1466
- ...
1467
- '''
1468
1574
  import atexit
1469
1575
  import sys
1470
1576
  import traceback
1577
+ from typing import Any
1578
+
1471
1579
  CHECK = "✅"
1472
1580
  CROSS = "❌"
1581
+ UNKNOWN = "❔"
1582
+
1473
1583
  code_mapping_failure = [0]
1474
- table = [
1475
- {"name": "tensorleap_preprocess", "Added to integration": CROSS},
1476
- {"name": "tensorleap_integration_test", "Added to integration": CROSS},
1477
- {"name": "tensorleap_input_encoder", "Added to integration": CROSS},
1478
- {"name": "tensorleap_gt_encoder", "Added to integration": CROSS},
1479
- {"name": "tensorleap_load_model", "Added to integration": CROSS},
1480
- {"name": "tensorleap_custom_loss", "Added to integration": CROSS},
1481
- {"name": "tensorleap_custom_metric (optional)", "Added to integration": CROSS},
1482
- {"name": "tensorleap_metadata (optional)", "Added to integration": CROSS},
1483
- {"name": "tensorleap_custom_visualizer (optional)", "Added to integration": CROSS},
1484
1584
 
1585
+ table = [
1586
+ {"name": "tensorleap_preprocess", "Added to integration": UNKNOWN},
1587
+ {"name": "tensorleap_integration_test", "Added to integration": UNKNOWN},
1588
+ {"name": "tensorleap_input_encoder", "Added to integration": UNKNOWN},
1589
+ {"name": "tensorleap_gt_encoder", "Added to integration": UNKNOWN},
1590
+ {"name": "tensorleap_load_model", "Added to integration": UNKNOWN},
1591
+ {"name": "tensorleap_custom_loss", "Added to integration": UNKNOWN},
1592
+ {"name": "tensorleap_custom_metric (optional)", "Added to integration": UNKNOWN},
1593
+ {"name": "tensorleap_metadata (optional)", "Added to integration": UNKNOWN},
1594
+ {"name": "tensorleap_custom_visualizer (optional)", "Added to integration": UNKNOWN},
1485
1595
  ]
1486
1596
 
1487
1597
  _finalizer_called = {"done": False}
1598
+ _crashed = {"value": False}
1599
+ _current_func = {"name": None}
1600
+
1601
+ def _link(url: str) -> str:
1602
+ return f"\033{url}\033"
1488
1603
 
1489
1604
  def _remove_suffix(s: str, suffix: str) -> str:
1490
- # This is needed because str.remove_suffix was presented in python3.9+
1491
1605
  if suffix and s.endswith(suffix):
1492
1606
  return s[:-len(suffix)]
1493
1607
  return s
1494
1608
 
1609
+ def _find_row(name: str):
1610
+ for row in table:
1611
+ if _remove_suffix(row["name"], " (optional)") == name:
1612
+ return row
1613
+ return None
1614
+
1615
+ def _set_status(name: str, status_symbol: str):
1616
+ row = _find_row(name)
1617
+ if not row:
1618
+ return
1619
+
1620
+ cur = row["Added to integration"]
1621
+ if status_symbol == UNKNOWN:
1622
+ return
1623
+ if cur == CHECK and status_symbol != CHECK:
1624
+ return
1625
+
1626
+ row["Added to integration"] = status_symbol
1627
+
1628
+ def _mark_unknowns_as_cross():
1629
+ for row in table:
1630
+ if row["Added to integration"] == UNKNOWN:
1631
+ row["Added to integration"] = CROSS
1632
+
1633
+ def _format_default_value(v: Any) -> str:
1634
+ if hasattr(v, "name"):
1635
+ return str(v.name)
1636
+ if isinstance(v, str):
1637
+ return v
1638
+ s = repr(v)
1639
+ return s if len(s) <= 120 else s[:120] + "..."
1640
+
1641
+ def _print_param_default_warnings():
1642
+ data = _get_param_default_warnings()
1643
+ if not data:
1644
+ return
1645
+
1646
+ print("\nWarnings (Default use. It is recommended to set values explicitly):")
1647
+ for param_name in sorted(data.keys()):
1648
+ default_value = data[param_name]["default_value"]
1649
+ funcs = ", ".join(sorted(data[param_name]["funcs"]))
1650
+ dv = _format_default_value(default_value)
1651
+
1652
+ docs_link = data[param_name].get("link_to_docs")
1653
+ docs_part = f" {_link(docs_link)}" if docs_link else ""
1654
+ print(
1655
+ f" ⚠️ Parameter '{param_name}' defaults to {dv} in the following functions: [{funcs}]. "
1656
+ f"For more information, check {docs_part}")
1657
+ print("\nIf this isn’t the intended behaviour, set them explicitly.")
1658
+
1495
1659
  def _print_table():
1660
+ _print_param_default_warnings()
1661
+
1662
+ if not started_from("leap_integration.py"):
1663
+ return
1664
+
1496
1665
  ready_mess = "\nAll parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system."
1497
1666
  not_ready_mess = "\nSome mandatory components have not yet been added to the Integration test. Recommended next interface to add is: "
1498
1667
  mandatory_ready_mess = "\nAll mandatory parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system or continue to the next optional reccomeded interface,adding: "
@@ -1500,48 +1669,75 @@ def tensorleap_status_table():
1500
1669
 
1501
1670
  name_width = max(len(row["name"]) for row in table)
1502
1671
  status_width = max(len(row["Added to integration"]) for row in table)
1672
+
1503
1673
  header = f"{'Decorator Name'.ljust(name_width)} | {'Added to integration'.ljust(status_width)}"
1504
1674
  sep = "-" * len(header)
1675
+
1505
1676
  print("\n" + header)
1506
1677
  print(sep)
1678
+
1507
1679
  ready = True
1680
+ next_step = None
1681
+
1508
1682
  for row in table:
1509
1683
  print(f"{row['name'].ljust(name_width)} | {row['Added to integration'].ljust(status_width)}")
1510
- if row['Added to integration'] == CROSS and ready:
1511
- ready = False
1512
- next_step = row['name']
1684
+ if not _crashed["value"] and ready:
1685
+ if row["Added to integration"] != CHECK:
1686
+ ready = False
1687
+ next_step = row["name"]
1688
+
1689
+ if _crashed["value"]:
1690
+ print(f"\nScript crashed before completing all steps. crashed at function '{_current_func['name']}'.")
1691
+ return
1513
1692
 
1514
1693
  if code_mapping_failure[0]:
1515
1694
  print(f"\n{CROSS + code_mapping_failure_mes}.")
1516
- else:
1517
- print(ready_mess) if ready else print(
1518
- mandatory_ready_mess + next_step) if "optional" in next_step else print(not_ready_mess + next_step)
1695
+ return
1519
1696
 
1520
- def update_env_params(name: str, status: str = "✓"):
1521
- for row in table:
1522
- if _remove_suffix(row["name"], " (optional)") == name:
1523
- row["Added to integration"] = CHECK if status == "v" else CROSS
1524
- break
1697
+ print(ready_mess) if ready else print(
1698
+ mandatory_ready_mess + next_step
1699
+ ) if (next_step and "optional" in next_step) else print(not_ready_mess + (next_step or ""))
1700
+
1701
+ def set_current(name: str):
1702
+ _current_func["name"] = name
1703
+
1704
+ def update_env_params(name: str, status: str = "v"):
1525
1705
  if name == "code_mapping":
1526
1706
  code_mapping_failure[0] = 1
1707
+ if status == "v":
1708
+ _set_status(name, CHECK)
1709
+ else:
1710
+ _set_status(name, CROSS)
1527
1711
 
1528
1712
  def run_on_exit():
1529
1713
  if _finalizer_called["done"]:
1530
1714
  return
1531
1715
  _finalizer_called["done"] = True
1716
+ if not _crashed["value"]:
1717
+ _mark_unknowns_as_cross()
1718
+
1532
1719
  _print_table()
1533
1720
 
1534
1721
  def handle_exception(exc_type, exc_value, exc_traceback):
1722
+ _crashed["value"] = True
1723
+ crashed_name = _current_func["name"]
1724
+ if crashed_name:
1725
+ row = _find_row(crashed_name)
1726
+ if row and row["Added to integration"] != CHECK:
1727
+ row["Added to integration"] = CROSS
1728
+
1535
1729
  traceback.print_exception(exc_type, exc_value, exc_traceback)
1536
1730
  run_on_exit()
1537
1731
 
1538
1732
  atexit.register(run_on_exit)
1539
1733
  sys.excepthook = handle_exception
1540
- return update_env_params
1734
+
1735
+ return set_current, update_env_params
1541
1736
 
1542
1737
 
1543
1738
  if not _call_from_tl_platform:
1544
- update_env_params_func = tensorleap_status_table()
1739
+ set_current, update_env_params_func = tensorleap_status_table()
1740
+
1545
1741
 
1546
1742
 
1547
1743
 
@@ -521,11 +521,11 @@ class LeapLoader(LeapLoaderBase):
521
521
 
522
522
  return converted_value, is_none
523
523
 
524
- def get_metadata(self, state: DataStateEnum, sample_id: Union[int, str], only_metadata_names: Optional[List[str]] = None) -> Tuple[
524
+ def get_metadata(self, state: DataStateEnum, sample_id: Union[int, str], requested_metadata_names: Optional[List[str]] = None) -> Tuple[
525
525
  Dict[str, Union[str, int, bool, float]], Dict[str, bool]]:
526
526
 
527
527
  def is_metadata_name_starts_with_handler_name(_handler):
528
- for metadata_name in only_metadata_names:
528
+ for metadata_name in requested_metadata_names:
529
529
  if metadata_name.startswith(_handler.name + '_') or metadata_name == _handler.name:
530
530
  return True
531
531
  return False
@@ -535,7 +535,7 @@ class LeapLoader(LeapLoaderBase):
535
535
  preprocess_result = self._preprocess_result()
536
536
  preprocess_state = preprocess_result[state]
537
537
  for handler in global_leap_binder.setup_container.metadata:
538
- if only_metadata_names:
538
+ if requested_metadata_names:
539
539
  if not is_metadata_name_starts_with_handler_name(handler):
540
540
  continue
541
541
 
@@ -543,15 +543,15 @@ class LeapLoader(LeapLoaderBase):
543
543
  if isinstance(handler_result, dict):
544
544
  for single_metadata_name, single_metadata_result in handler_result.items():
545
545
  handler_name = f'{handler.name}_{single_metadata_name}'
546
- if only_metadata_names:
547
- if handler_name not in only_metadata_names:
546
+ if requested_metadata_names:
547
+ if handler_name not in requested_metadata_names:
548
548
  continue
549
549
  result_agg[handler_name], is_none[handler_name] = self._convert_metadata_to_correct_type(
550
550
  handler_name, single_metadata_result)
551
551
  else:
552
552
  handler_name = handler.name
553
- if only_metadata_names:
554
- if handler_name not in only_metadata_names:
553
+ if requested_metadata_names:
554
+ if handler_name not in requested_metadata_names:
555
555
  continue
556
556
  result_agg[handler_name], is_none[handler_name] = self._convert_metadata_to_correct_type(
557
557
  handler_name, handler_result)
@@ -69,7 +69,7 @@ class LeapLoaderBase:
69
69
  pass
70
70
 
71
71
  def get_metadata_multiple_samples(self, state: DataStateEnum, sample_ids: Union[List[int], List[str]],
72
- only_metadata_names: Optional[List[str]] = None
72
+ requested_metadata_names: Optional[List[str]] = None
73
73
  ) -> Tuple[Dict[str, Union[List[str], List[int], List[bool],
74
74
  List[float]]], Dict[str, List[bool]]]:
75
75
  aggregated_results: Dict[str, List[Union[str, int, bool, float]]] = {}
@@ -77,7 +77,7 @@ class LeapLoaderBase:
77
77
  sample_id_type = self.get_sample_id_type()
78
78
  for sample_id in sample_ids:
79
79
  sample_id = sample_id_type(sample_id)
80
- metadata_result, is_none_result = self.get_metadata(state, sample_id, only_metadata_names)
80
+ metadata_result, is_none_result = self.get_metadata(state, sample_id, requested_metadata_names)
81
81
  for metadata_name, metadata_value in metadata_result.items():
82
82
  if metadata_name not in aggregated_results:
83
83
  aggregated_results[metadata_name] = []
@@ -108,7 +108,7 @@ class LeapLoaderBase:
108
108
  @abstractmethod
109
109
  def get_metadata(
110
110
  self, state: DataStateEnum, sample_id: Union[int, str],
111
- only_metadata_names: Optional[List[str]] = None
111
+ requested_metadata_names: Optional[List[str]] = None
112
112
  ) -> Tuple[Dict[str, Union[str, int, bool, float]], Dict[str, bool]]:
113
113
  pass
114
114
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "code-loader"
3
- version = "1.0.151.dev3"
3
+ version = "1.0.152.dev1"
4
4
  description = ""
5
5
  authors = ["dorhar <doron.harnoy@tensorleap.ai>"]
6
6
  license = "MIT"