code-loader 1.0.180.dev2__tar.gz → 1.0.180.dev4__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 (37) hide show
  1. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/PKG-INFO +1 -1
  2. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/datasetclasses.py +4 -3
  3. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/responsedataclasses.py +2 -2
  4. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/inner_leap_binder/leapbinder.py +3 -3
  5. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/inner_leap_binder/leapbinder_decorators.py +79 -6
  6. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/leaploader.py +2 -66
  7. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/leaploaderbase.py +1 -6
  8. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/mixpanel_tracker.py +1 -0
  9. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/pyproject.toml +1 -1
  10. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/LICENSE +0 -0
  11. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/README.md +0 -0
  12. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/__init__.py +0 -0
  13. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/__init__.py +0 -0
  14. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/enums.py +0 -0
  15. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/exceptions.py +0 -0
  16. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/mapping.py +0 -0
  17. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/sim_config.py +0 -0
  18. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/contract/visualizer_classes.py +0 -0
  19. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/default_losses.py +0 -0
  20. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/default_metrics.py +0 -0
  21. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/__init__.py +0 -0
  22. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/api.py +0 -0
  23. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/cli_config_utils.py +0 -0
  24. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/client.py +0 -0
  25. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/epoch.py +0 -0
  26. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/experiment.py +0 -0
  27. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/experiment_context.py +0 -0
  28. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/types.py +0 -0
  29. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/utils.py +0 -0
  30. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
  31. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/inner_leap_binder/__init__.py +0 -0
  32. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/plot_functions/__init__.py +0 -0
  33. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/plot_functions/plot_functions.py +0 -0
  34. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/plot_functions/visualize.py +0 -0
  35. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/utils.py +0 -0
  36. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/code_loader/visualizers/__init__.py +0 -0
  37. {code_loader-1.0.180.dev2 → code_loader-1.0.180.dev4}/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.180.dev2
3
+ Version: 1.0.180.dev4
4
4
  Summary:
5
5
  Home-page: https://github.com/tensorleap/code-loader
6
6
  License: MIT
@@ -42,6 +42,7 @@ class PreprocessResponse:
42
42
  sample_id_type: Optional[Union[Type[str], Type[int]]] = None
43
43
  sample_ids_to_instance_mappings: Optional[Dict[str, List[str]]] = None # in use only for element instance
44
44
  instance_to_sample_ids_mappings: Optional[Dict[str, str]] = None # in use only for element instance
45
+ tl_generated: bool = False
45
46
 
46
47
  def __post_init__(self) -> None:
47
48
  assert self.sample_ids_to_instance_mappings is None, f"Keep sample_ids_to_instance_mappings None when initializing PreprocessResponse"
@@ -254,9 +255,9 @@ class CustomLayerHandler:
254
255
 
255
256
 
256
257
  @dataclass
257
- class SimulationInstance:
258
+ class SimulationHandler:
258
259
  name: str
259
- function: Callable[..., Any]
260
+ function: Callable[..., PreprocessResponse]
260
261
  sim_config: SimConfig
261
262
 
262
263
 
@@ -275,7 +276,7 @@ class DatasetIntegrationSetup:
275
276
  instance_metrics: List[InstanceMetricHandler] = field(default_factory=list)
276
277
  custom_layers: Dict[str, CustomLayerHandler] = field(default_factory=dict)
277
278
  custom_latent_space: Optional[CustomLatentSpaceHandler] = None
278
- simulations: List[SimulationInstance] = field(default_factory=list)
279
+ simulations: List[SimulationHandler] = field(default_factory=list)
279
280
 
280
281
 
281
282
  @dataclass
@@ -70,7 +70,7 @@ class PredictionTypeInstance:
70
70
 
71
71
 
72
72
  @dataclass
73
- class SimulationSetupInstance:
73
+ class SimulationInstance:
74
74
  name: str
75
75
  sim_config: Dict[str, Any]
76
76
 
@@ -85,7 +85,7 @@ class DatasetSetup:
85
85
  prediction_types: List[PredictionTypeInstance]
86
86
  custom_losses: List[CustomLossInstance]
87
87
  metrics: List[MetricInstance] = field(default_factory=list)
88
- simulations: List[SimulationSetupInstance] = field(default_factory=list)
88
+ simulations: List[SimulationInstance] = field(default_factory=list)
89
89
 
90
90
 
91
91
  @dataclass
@@ -13,7 +13,7 @@ from code_loader.contract.datasetclasses import SectionCallableInterface, InputH
13
13
  CustomMultipleReturnCallableInterfaceMultiArgs, DatasetBaseHandler, custom_latent_space_attribute, \
14
14
  RawInputsForHeatmap, VisualizerHandlerData, MetricHandlerData, CustomLossHandlerData, SamplePreprocessResponse, \
15
15
  ElementInstanceMasksHandler, InstanceCallableInterface, CustomLatentSpaceHandler, InstanceMetricHandler, \
16
- SimulationInstance
16
+ SimulationHandler
17
17
  from code_loader.contract.enums import LeapDataType, DataStateEnum, DataStateType, MetricDirection, DatasetMetadataType
18
18
  from code_loader.contract.mapping import NodeConnection, NodeMapping, NodeMappingType
19
19
  from code_loader.contract.responsedataclasses import DatasetTestResultPayload, LeapAnalysisConfiguration
@@ -221,7 +221,7 @@ class LeapBinder:
221
221
  """
222
222
  self.setup_container.unlabeled_data_preprocess = UnlabeledDataPreprocessHandler(function)
223
223
 
224
- def set_simulation(self, function: Callable[..., Any], name: str, sim_config_raw: Dict[str, Any]) -> None:
224
+ def set_simulation(self, function: Callable[..., PreprocessResponse], name: str, sim_config_raw: Dict[str, Any]) -> None:
225
225
  for sim in self.setup_container.simulations:
226
226
  if sim.name == name:
227
227
  raise Exception(
@@ -229,7 +229,7 @@ class LeapBinder:
229
229
  )
230
230
  sim_config = parse_sim_config(sim_config_raw)
231
231
  self.setup_container.simulations.append(
232
- SimulationInstance(name=name, function=function, sim_config=sim_config)
232
+ SimulationHandler(name=name, function=function, sim_config=sim_config)
233
233
  )
234
234
 
235
235
  def set_input(self, function: SectionCallableInterface, name: str, channel_dim: int = -1) -> None:
@@ -1400,7 +1400,7 @@ def tensorleap_preprocess():
1400
1400
 
1401
1401
 
1402
1402
  def tensorleap_simulation(name: str, sim_params: dict):
1403
- def decorating_function(user_function: Callable):
1403
+ def decorating_function(user_function: Callable[..., PreprocessResponse]):
1404
1404
  sig = inspect.signature(user_function)
1405
1405
  func_params = set(sig.parameters.keys())
1406
1406
  expected_params = set(sim_params.keys()) | {"N"}
@@ -1423,13 +1423,54 @@ def tensorleap_simulation(name: str, sim_params: dict):
1423
1423
 
1424
1424
  leap_binder.set_simulation(user_function, name, sim_params)
1425
1425
 
1426
- def inner(*args, **kwargs):
1427
- result = user_function(*args, **kwargs)
1426
+ if not _call_from_tl_platform:
1427
+ register_sim(name)
1428
+
1429
+ def _validate_input_args(*args, **kwargs):
1430
+ assert len(args) == 0, (
1431
+ f"{user_function.__name__}() validation failed: "
1432
+ f"Simulation functions must be called with keyword arguments only. Got positional args: {args}."
1433
+ )
1434
+ missing = expected_params - set(kwargs.keys())
1435
+ assert not missing, (
1436
+ f"{user_function.__name__}() validation failed: "
1437
+ f"Missing required keyword arguments: {missing}."
1438
+ )
1439
+
1440
+ def _validate_result(result):
1428
1441
  assert isinstance(result, PreprocessResponse), (
1429
1442
  f"{user_function.__name__}() validation failed: "
1430
1443
  f"Expected return type PreprocessResponse. Got {type(result).__name__}."
1431
1444
  )
1432
- return result
1445
+
1446
+ def inner(*args, **kwargs):
1447
+ if not _call_from_tl_platform:
1448
+ set_current('tensorleap simulation')
1449
+ try:
1450
+ _validate_input_args(*args, **kwargs)
1451
+ result = user_function(*args, **kwargs)
1452
+ _validate_result(result)
1453
+ if result.state != DataStateType.additional:
1454
+ logger.warning(
1455
+ f"{user_function.__name__}() returned state={result.state!r}; "
1456
+ f"overriding to DataStateType.additional."
1457
+ )
1458
+ result.state = DataStateType.additional
1459
+ result.tl_generated = True
1460
+ try:
1461
+ emit_integration_event_once(AnalyticsEvent.SIMULATION_INTEGRATION_TEST, {
1462
+ 'simulation_name': name,
1463
+ 'sim_params_count': len(sim_params)
1464
+ })
1465
+ except Exception as e:
1466
+ logger.debug(f"Failed to emit simulation integration test event: {e}")
1467
+ if not _call_from_tl_platform:
1468
+ mark_sim_result(name, True)
1469
+ return result
1470
+ except Exception:
1471
+ if not _call_from_tl_platform:
1472
+ mark_sim_result(name, False)
1473
+ raise
1433
1474
 
1434
1475
  return inner
1435
1476
 
@@ -2057,6 +2098,9 @@ def tensorleap_status_table():
2057
2098
  def _print_table():
2058
2099
  _print_param_default_warnings()
2059
2100
 
2101
+ for msg in _sim_messages:
2102
+ print(f"\n⚠️ {msg}")
2103
+
2060
2104
  if not started_from("leap_integration.py"):
2061
2105
  return
2062
2106
 
@@ -2109,12 +2153,41 @@ def tensorleap_status_table():
2109
2153
  else:
2110
2154
  _set_status(name, CROSS)
2111
2155
 
2156
+ _sim_tracking: dict = {}
2157
+ _sim_messages: list = []
2158
+
2159
+ def register_sim(sim_name: str):
2160
+ if not _sim_tracking:
2161
+ table.append({"name": "tensorleap simulation (optional)", "Added to integration": UNKNOWN})
2162
+ _sim_tracking[sim_name] = "registered"
2163
+
2164
+ def mark_sim_result(sim_name: str, passed: bool):
2165
+ _sim_tracking[sim_name] = "passed" if passed else "failed"
2166
+
2167
+ def _resolve_sim_row():
2168
+ if not _sim_tracking:
2169
+ return
2170
+ row = _find_row("tensorleap simulation")
2171
+ if not row:
2172
+ return
2173
+ failed = [n for n, s in _sim_tracking.items() if s == "failed"]
2174
+ not_called = [n for n, s in _sim_tracking.items() if s == "registered"]
2175
+ if failed:
2176
+ row["Added to integration"] = CROSS
2177
+ _sim_messages.append(f"Simulation(s) failed validation: {', '.join(sorted(failed))}")
2178
+ elif not_called:
2179
+ row["Added to integration"] = UNKNOWN
2180
+ _sim_messages.append(f"Simulation(s) not called in integration test: {', '.join(sorted(not_called))}")
2181
+ else:
2182
+ row["Added to integration"] = CHECK
2183
+
2112
2184
  def run_on_exit():
2113
2185
  if _finalizer_called["done"]:
2114
2186
  return
2115
2187
  _finalizer_called["done"] = True
2116
2188
  if not _crashed["value"]:
2117
2189
  _mark_unknowns_as_cross()
2190
+ _resolve_sim_row()
2118
2191
 
2119
2192
  _print_table()
2120
2193
 
@@ -2132,11 +2205,11 @@ def tensorleap_status_table():
2132
2205
  atexit.register(run_on_exit)
2133
2206
  sys.excepthook = handle_exception
2134
2207
 
2135
- return set_current, update_env_params
2208
+ return set_current, update_env_params, register_sim, mark_sim_result
2136
2209
 
2137
2210
 
2138
2211
  if not _call_from_tl_platform:
2139
- set_current, update_env_params_func = tensorleap_status_table()
2212
+ set_current, update_env_params_func, register_sim, mark_sim_result = tensorleap_status_table()
2140
2213
 
2141
2214
 
2142
2215
 
@@ -22,7 +22,7 @@ from code_loader.contract.exceptions import DatasetScriptException
22
22
  from code_loader.contract.responsedataclasses import DatasetIntegParseResult, DatasetTestResultPayload, \
23
23
  DatasetPreprocess, DatasetSetup, DatasetInputInstance, DatasetOutputInstance, DatasetMetadataInstance, \
24
24
  VisualizerInstance, PredictionTypeInstance, ModelSetup, CustomLayerInstance, MetricInstance, CustomLossInstance, \
25
- EngineFileContract, SimulationSetupInstance
25
+ EngineFileContract, SimulationInstance
26
26
  from code_loader.contract.sim_config import FloatBounds, IntBounds, CategoricalBounds
27
27
  from code_loader.inner_leap_binder import global_leap_binder
28
28
  from code_loader.inner_leap_binder.leapbinder import mapping_runtime_mode_env_var_mame
@@ -38,20 +38,6 @@ def _serialize_sim_bounds(bounds) -> dict:
38
38
  raise ValueError(f"Unknown bounds type: {type(bounds)}")
39
39
 
40
40
 
41
- def _sample_sim_params(sim_config):
42
- # type: (Dict[str, Any]) -> Dict[str, Any]
43
- params = {}
44
- for name, param_config in sim_config.items():
45
- bounds = param_config.bounds
46
- if isinstance(bounds, FloatBounds):
47
- params[name] = (bounds.min + bounds.max) / 2.0
48
- elif isinstance(bounds, IntBounds):
49
- params[name] = int((bounds.min + bounds.max) / 2)
50
- else: # CategoricalBounds
51
- params[name] = bounds.values[0]
52
- return params
53
-
54
-
55
41
  class LeapLoader(LeapLoaderBase):
56
42
  def __init__(self, code_path: str, code_entry_name: str):
57
43
  super().__init__(code_path, code_entry_name)
@@ -237,8 +223,6 @@ class LeapLoader(LeapLoaderBase):
237
223
  test_payloads.append(preprocess_test_payload)
238
224
  handlers_test_payloads = self._check_handlers()
239
225
  test_payloads.extend(handlers_test_payloads)
240
- simulation_test_payloads = self._check_simulations()
241
- test_payloads.extend(simulation_test_payloads)
242
226
  is_valid = all([payload.is_passed for payload in test_payloads])
243
227
  setup_response = self.get_dataset_setup_response(handlers_test_payloads)
244
228
 
@@ -315,54 +299,6 @@ class LeapLoader(LeapLoaderBase):
315
299
  result_payloads.extend(test_result)
316
300
  return result_payloads
317
301
 
318
- def _check_simulations(self):
319
- # type: () -> List[DatasetTestResultPayload]
320
- result_payloads = []
321
- for sim in global_leap_binder.setup_container.simulations:
322
- test_result = DatasetTestResultPayload(sim.name)
323
- try:
324
- kwargs = _sample_sim_params(sim.sim_config)
325
- kwargs["N"] = 1
326
- if "seed" in inspect.signature(sim.function).parameters:
327
- kwargs["seed"] = 0
328
- preprocess_response = sim.function(**kwargs)
329
- if not isinstance(preprocess_response, PreprocessResponse):
330
- raise TypeError(
331
- "Expected PreprocessResponse, got {}".format(type(preprocess_response).__name__)
332
- )
333
- if preprocess_response.length < 1:
334
- raise ValueError("Simulation returned PreprocessResponse with length < 1")
335
- except Exception as e:
336
- line_number, file_name, stacktrace = get_root_exception_file_and_line_number()
337
- test_result.display[TestingSectionEnum.Errors.name] = (
338
- "{} in file {}, line_number: {}\nStacktrace:\n{}".format(
339
- repr(e), file_name, line_number, stacktrace
340
- )
341
- )
342
- test_result.is_passed = False
343
- result_payloads.append(test_result)
344
- return result_payloads
345
-
346
- def run_simulation_check(self, sim_name):
347
- # type: (str) -> Dict[str, npt.NDArray[np.float32]]
348
- self.exec_script()
349
- sim = next(
350
- (s for s in global_leap_binder.setup_container.simulations if s.name == sim_name),
351
- None,
352
- )
353
- if sim is None:
354
- raise ValueError("No simulation registered with name '{}'".format(sim_name))
355
- kwargs = _sample_sim_params(sim.sim_config)
356
- kwargs["N"] = 1
357
- if "seed" in inspect.signature(sim.function).parameters:
358
- kwargs["seed"] = 0
359
- sim_preprocess = sim.function(**kwargs)
360
- sim_preprocess.state = DataStateType.additional
361
- result = {}
362
- for handler in global_leap_binder.setup_container.inputs:
363
- result[handler.name] = handler.function(0, sim_preprocess)
364
- return result
365
-
366
302
  @staticmethod
367
303
  def _get_all_dataset_base_handlers() -> List[Union[DatasetBaseHandler, MetadataHandler]]:
368
304
  all_dataset_base_handlers: List[Union[DatasetBaseHandler, MetadataHandler]] = []
@@ -536,7 +472,7 @@ class LeapLoader(LeapLoaderBase):
536
472
  }
537
473
  for name, param in sim.sim_config.items()
538
474
  }
539
- simulations.append(SimulationSetupInstance(name=sim.name, sim_config=sim_config_serialized))
475
+ simulations.append(SimulationInstance(name=sim.name, sim_config=sim_config_serialized))
540
476
 
541
477
  return DatasetSetup(preprocess=dataset_preprocess, inputs=inputs, outputs=ground_truths,
542
478
  metadata=metadata_instances, visualizers=visualizers, prediction_types=prediction_types,
@@ -2,7 +2,7 @@
2
2
 
3
3
  from abc import abstractmethod
4
4
 
5
- from typing import Any, Dict, List, Union, Type, Optional, Tuple
5
+ from typing import Dict, List, Union, Type, Optional, Tuple
6
6
 
7
7
  import numpy as np
8
8
  import numpy.typing as npt
@@ -153,11 +153,6 @@ class LeapLoaderBase:
153
153
  def get_heatmap_visualizer_raw_vis_input_arg_name(self, visualizer_name: str) -> Optional[str]:
154
154
  pass
155
155
 
156
- @abstractmethod
157
- def run_simulation_check(self, sim_name):
158
- # type: (str) -> Dict[str, Any]
159
- pass
160
-
161
156
  def is_custom_latent_space(self) -> bool:
162
157
  if not self.code_entry_name or not self.code_path:
163
158
  return False
@@ -23,6 +23,7 @@ class AnalyticsEvent(str, Enum):
23
23
  PREPROCESS_INTEGRATION_TEST = "preprocess_integration_test"
24
24
  INPUT_ENCODER_INTEGRATION_TEST = "input_encoder_integration_test"
25
25
  GT_ENCODER_INTEGRATION_TEST = "gt_encoder_integration_test"
26
+ SIMULATION_INTEGRATION_TEST = "simulation_integration_test"
26
27
 
27
28
 
28
29
  class CodeLoaderLoadedProps(TypedDict, total=False):
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "code-loader"
3
- version = "1.0.180.dev2"
3
+ version = "1.0.180.dev4"
4
4
  description = ""
5
5
  authors = ["dorhar <doron.harnoy@tensorleap.ai>"]
6
6
  license = "MIT"