code-loader 1.0.139.dev2__py3-none-any.whl → 1.0.139.dev4__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 code-loader might be problematic. Click here for more details.

@@ -1,4 +1,3 @@
1
- import warnings
2
1
  from dataclasses import dataclass, field
3
2
  from typing import Any, Callable, List, Optional, Dict, Union, Type
4
3
  import re
@@ -57,14 +56,7 @@ class PreprocessResponse:
57
56
  for sample_id in self.sample_ids:
58
57
  assert isinstance(sample_id, str), f"Sample id should be of type str. Got: {type(sample_id)}"
59
58
  else:
60
- raise Exception("length is deprecated, please use sample_ids instead.")
61
-
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."
65
- )
66
- else:
67
- assert isinstance(self.state, DataStateType), f"PreprocessResponse.state must be of type {DataStateType.__name__} but got {type(self.state)}"
59
+ raise Exception("length is deprecated.")
68
60
 
69
61
  def __hash__(self) -> int:
70
62
  return id(self)
@@ -1,10 +1,9 @@
1
1
  # mypy: ignore-errors
2
2
  import os
3
- import warnings
4
3
  from collections import defaultdict
5
4
  from functools import lru_cache
6
5
  from pathlib import Path
7
- from typing import Optional, Union, Callable, List, Dict, get_args, get_origin
6
+ from typing import Optional, Union, Callable, List, Dict, Set, Any
8
7
 
9
8
  import numpy as np
10
9
  import numpy.typing as npt
@@ -26,116 +25,9 @@ import functools
26
25
 
27
26
  _called_from_inside_tl_decorator = 0
28
27
  _called_from_inside_tl_integration_test_decorator = False
29
- _update_env_status = None
30
-
31
-
32
-
33
-
34
- def validate_args_structure(*args, types_order, func_name, expected_names, **kwargs):
35
- def _type_to_str(t):
36
- origin = get_origin(t)
37
- if origin is Union:
38
- return " | ".join(tt.__name__ for tt in get_args(t))
39
- elif hasattr(t, "__name__"):
40
- return t.__name__
41
- else:
42
- return str(t)
43
-
44
- def _format_types(types, names=None):
45
- return ", ".join(
46
- f"{(names[i] + ': ') if names else f'arg{i}: '}{_type_to_str(ty)}"
47
- for i, ty in enumerate(types)
48
- )
49
-
50
- if expected_names:
51
- normalized_args = []
52
- for i, name in enumerate(expected_names):
53
- if i < len(args):
54
- normalized_args.append(args[i])
55
- elif name in kwargs:
56
- normalized_args.append(kwargs[name])
57
- else:
58
- raise AssertionError(
59
- f"{func_name} validation failed: "
60
- f"Missing required argument '{name}'. "
61
- f"Expected arguments: {expected_names}."
62
- )
63
- else:
64
- normalized_args = list(args)
65
- if len(normalized_args) != len(types_order):
66
- expected = _format_types(types_order, expected_names)
67
- got_types = ", ".join(type(arg).__name__ for arg in normalized_args)
68
- raise AssertionError(
69
- f"{func_name} validation failed: "
70
- f"Expected exactly {len(types_order)} arguments ({expected}), "
71
- f"but got {len(normalized_args)} argument(s) of type(s): ({got_types}). "
72
- f"Correct usage example: {func_name}({expected})"
73
- )
74
-
75
- for i, (arg, expected_type) in enumerate(zip(normalized_args, types_order)):
76
- origin = get_origin(expected_type)
77
- if origin is Union:
78
- allowed_types = get_args(expected_type)
79
- else:
80
- allowed_types = (expected_type,)
81
-
82
- if not isinstance(arg, allowed_types):
83
- allowed_str = " | ".join(t.__name__ for t in allowed_types)
84
- raise AssertionError(
85
- f"{func_name} validation failed: "
86
- f"Argument '{expected_names[i] if expected_names else f'arg{i}'}' "
87
- f"expected type {allowed_str}, but got {type(arg).__name__}. "
88
- f"Correct usage example: {func_name}({_format_types(types_order, expected_names)})"
89
- )
90
-
91
-
92
- def validate_output_structure(result, func_name: str, expected_type_name="np.ndarray",gt_flag=False):
93
- if result is None or (isinstance(result, float) and np.isnan(result)):
94
- if gt_flag:
95
- raise AssertionError(
96
- f"{func_name} validation failed: "
97
- f"The function returned {result!r}. "
98
- f"If you are working with an unlabeled dataset and no ground truth is available, "
99
- f"use 'return np.array([], dtype=np.float32)' instead. "
100
- f"Otherwise, {func_name} expected a single {expected_type_name} object. "
101
- f"Make sure the function ends with 'return <{expected_type_name}>'."
102
- )
103
-
104
- raise AssertionError(
105
- f"{func_name} validation failed: "
106
- f"The function returned None. "
107
- f"Expected a single {expected_type_name} object. "
108
- f"Make sure the function ends with 'return <{expected_type_name}>'."
109
- )
110
- if isinstance(result, tuple):
111
- element_descriptions = [
112
- f"[{i}] type: {type(r).__name__}"
113
- for i, r in enumerate(result)
114
- ]
115
- element_summary = "\n ".join(element_descriptions)
116
-
117
- raise AssertionError(
118
- f"{func_name} validation failed: "
119
- f"The function returned multiple outputs ({len(result)} values), "
120
- f"but only a single {expected_type_name} is allowed.\n\n"
121
- f"Returned elements:\n"
122
- f" {element_summary}\n\n"
123
- f"Correct usage example:\n"
124
- f" def {func_name}(...):\n"
125
- f" return <{expected_type_name}>\n\n"
126
- f"If you intended to return multiple values, combine them into a single "
127
- f"{expected_type_name} (e.g., by concatenation or stacking)."
128
- )
129
-
130
- def batch_warning(result, func_name):
131
- if result.shape[0] == 1:
132
- warnings.warn(
133
- f"{func_name} warning: Tensorleap will add a batch dimension at axis 0 to the output of {func_name}, "
134
- f"although the detected size of axis 0 is already 1. "
135
- f"This may lead to an extra batch dimension (e.g., shape (1, 1, ...)). "
136
- f"Please ensure that the output of '{func_name}' is not already batched "
137
- f"to avoid computation errors."
138
- )
28
+ _integration_events_emitted: Set[str] = set()
29
+
30
+
139
31
  def _add_mapping_connection(user_unique_name, connection_destinations, arg_names, name, node_mapping_type):
140
32
  connection_destinations = [connection_destination for connection_destination in connection_destinations
141
33
  if not isinstance(connection_destination, SamplePreprocessResponse)]
@@ -158,23 +50,12 @@ def tensorleap_integration_test():
158
50
  def decorating_function(integration_test_function: Callable):
159
51
  leap_binder.integration_test_func = integration_test_function
160
52
 
161
- def _validate_input_args(*args, **kwargs):
162
- sample_id,preprocess_response=args
163
- assert type(sample_id) == preprocess_response.sample_id_type, (
164
- f"tensorleap_integration_test validation failed: "
165
- f"sample_id type ({type(sample_id).__name__}) does not match the expected "
166
- f"type ({preprocess_response.sample_id_type}) from the PreprocessResponse."
167
- )
168
-
169
53
  def inner(*args, **kwargs):
170
- validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
171
- func_name='integration_test',expected_names=["idx", "preprocess"],**kwargs)
172
- _validate_input_args(*args, **kwargs)
173
-
174
54
  global _called_from_inside_tl_integration_test_decorator
55
+ global _integration_events_emitted
56
+ _integration_events_emitted.clear() # Clear events for new test
175
57
  try:
176
58
  _called_from_inside_tl_integration_test_decorator = True
177
- _update_env_status("tensorleap_integration_test", "v")#put here because otherwise it will become v only if it finishes all the script
178
59
  ret = integration_test_function(*args, **kwargs)
179
60
 
180
61
  try:
@@ -187,7 +68,7 @@ def tensorleap_integration_test():
187
68
  line_number = first_tb.lineno
188
69
  if isinstance(e, TypeError) and 'is not subscriptable' in str(e):
189
70
  print(f'Invalid integration code. File {file_name}, line {line_number}: '
190
- f"indexing is supported only on the model's predictions inside the integration test. Please remove this indexing operation usage from the integration test code.")
71
+ f'Please remove this indexing operation usage from the integration test code.')
191
72
  else:
192
73
  print(f'Invalid integration code. File {file_name}, line {line_number}: '
193
74
  f'Integration test is only allowed to call Tensorleap decorators. '
@@ -199,8 +80,8 @@ def tensorleap_integration_test():
199
80
  _called_from_inside_tl_integration_test_decorator = False
200
81
 
201
82
  leap_binder.check()
202
- return inner
203
83
 
84
+ return inner
204
85
 
205
86
  return decorating_function
206
87
 
@@ -210,52 +91,31 @@ def _safe_get_item(key):
210
91
  except ValueError:
211
92
  raise Exception(f'Tensorleap currently supports models with no more then 10 inputs')
212
93
 
94
+ def _emit_integration_event_once(event_name: str, props: Dict[str, Any]) -> None:
95
+ """Emit an integration test event only once per test run."""
96
+ if event_name in _integration_events_emitted:
97
+ return
98
+
99
+ try:
100
+ from code_loader.mixpanel_tracker import track_integration_test_event
101
+ track_integration_test_event(event_name, props)
102
+ _integration_events_emitted.add(event_name)
103
+ except Exception:
104
+ pass
105
+
213
106
  def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]] = []):
214
- assert isinstance(prediction_types, list),(
215
- f"tensorleap_load_model validation failed: "
216
- f" prediction_types is an optional argument of type List[PredictionTypeHandler]] but got {type(prediction_types).__name__}."
217
- )
218
107
  for i, prediction_type in enumerate(prediction_types):
219
- assert isinstance(prediction_type, PredictionTypeHandler),(f"tensorleap_load_model validation failed: "
220
- f" prediction_types at position {i} must be of type PredictionTypeHandler but got {type(prediction_types[i]).__name__}.")
221
108
  leap_binder.add_prediction(prediction_type.name, prediction_type.labels, prediction_type.channel_dim, i)
222
109
 
223
- def _validate_result(result) -> None:
224
- valid_types=["onnxruntime","keras"]
225
- err_message=f"tensorleap_load_model validation failed:\nSupported models are Keras and onnxruntime only and non of them was returned."
226
- validate_output_structure(result, func_name="tensorleap_load_model", expected_type_name= [" | ".join(t for t in valid_types)][0])
227
- try:
228
- import keras
229
- except ImportError:
230
- keras = None
231
- try:
232
- import onnxruntime
233
- except ImportError:
234
- onnxruntime = None
235
-
236
- if not keras and not onnxruntime:
237
- raise AssertionError(err_message)
238
-
239
- is_keras_model = bool(keras and isinstance(result, getattr(keras, "Model", tuple())))
240
- is_onnx_model = bool(onnxruntime and isinstance(result, onnxruntime.InferenceSession))
241
-
242
- if not any([is_keras_model, is_onnx_model]):
243
- raise AssertionError( err_message)
244
-
245
-
246
-
247
110
  def decorating_function(load_model_func):
248
111
  class TempMapping:
249
112
  pass
250
113
 
251
114
  @lru_cache()
252
- def inner(*args, **kwargs):
253
- validate_args_structure(*args, types_order=[],
254
- func_name='tensorleap_load_model',expected_names=[],**kwargs)
115
+ def inner():
255
116
  class ModelPlaceholder:
256
117
  def __init__(self):
257
- self.model = load_model_func() #TODO- check why this fails on onnx model
258
- _validate_result(self.model)
118
+ self.model = load_model_func()
259
119
 
260
120
  # keras interface
261
121
  def __call__(self, arg):
@@ -319,9 +179,8 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
319
179
 
320
180
  def get_inputs(self):
321
181
  return self.model.get_inputs()
322
- model_placeholder=ModelPlaceholder()
323
- _update_env_status("tensorleap_load_model", "v")
324
- return model_placeholder
182
+
183
+ return ModelPlaceholder()
325
184
 
326
185
  def mapping_inner():
327
186
  class ModelOutputPlaceholder:
@@ -384,11 +243,12 @@ def tensorleap_load_model(prediction_types: Optional[List[PredictionTypeHandler]
384
243
 
385
244
  return ModelPlaceholder()
386
245
 
387
- def final_inner(*args, **kwargs):
246
+ def final_inner():
388
247
  if os.environ.get(mapping_runtime_mode_env_var_mame):
389
248
  return mapping_inner()
390
249
  else:
391
- return inner(*args, **kwargs)
250
+ return inner()
251
+
392
252
  return final_inner
393
253
 
394
254
  return decorating_function
@@ -399,168 +259,81 @@ def tensorleap_custom_metric(name: str,
399
259
  compute_insights: Optional[Union[bool, Dict[str, bool]]] = None,
400
260
  connects_to=None):
401
261
  name_to_unique_name = defaultdict(set)
262
+
402
263
  def decorating_function(
403
264
  user_function: Union[CustomCallableInterfaceMultiArgs, CustomMultipleReturnCallableInterfaceMultiArgs,
404
265
  ConfusionMatrixCallableInterfaceMultiArgs]):
405
-
406
- def _validate_decorators_signature():
407
- err_message = f"{user_function.__name__} validation failed.\n"
408
- if not isinstance(name, str):
409
- raise TypeError(err_message + f"`name` must be a string, got type {type(name).__name__}.")
410
- valid_directions = {MetricDirection.Upward, MetricDirection.Downward}
411
- if isinstance(direction, MetricDirection):
412
- if direction not in valid_directions:
413
- raise ValueError(
414
- err_message +
415
- f"Invalid MetricDirection: {direction}. Must be one of {valid_directions}, "
416
- f"got type {type(direction).__name__}."
417
- )
418
- elif isinstance(direction, dict):
419
- if not all(isinstance(k, str) for k in direction.keys()):
420
- invalid_keys = {k: type(k).__name__ for k in direction.keys() if not isinstance(k, str)}
421
- raise TypeError(
422
- err_message +
423
- f"All keys in `direction` must be strings, got invalid key types: {invalid_keys}."
424
- )
425
- for k, v in direction.items():
426
- if v not in valid_directions:
427
- raise ValueError(
428
- err_message +
429
- f"Invalid direction for key '{k}': {v}. Must be one of {valid_directions}, "
430
- f"got type {type(v).__name__}."
431
- )
432
- else:
433
- raise TypeError(
434
- err_message +
435
- f"`direction` must be a MetricDirection or a Dict[str, MetricDirection], "
436
- f"got type {type(direction).__name__}."
437
- )
438
- if compute_insights is not None:
439
- if not isinstance(compute_insights, (bool, dict)):
440
- raise TypeError(
441
- err_message +
442
- f"`compute_insights` must be a bool or a Dict[str, bool], "
443
- f"got type {type(compute_insights).__name__}."
444
- )
445
- if isinstance(compute_insights, dict):
446
- if not all(isinstance(k, str) for k in compute_insights.keys()):
447
- invalid_keys = {k: type(k).__name__ for k in compute_insights.keys() if not isinstance(k, str)}
448
- raise TypeError(
449
- err_message +
450
- f"All keys in `compute_insights` must be strings, got invalid key types: {invalid_keys}."
451
- )
452
- for k, v in compute_insights.items():
453
- if not isinstance(v, bool):
454
- raise TypeError(
455
- err_message +
456
- f"Invalid type for compute_insights['{k}']: expected bool, got type {type(v).__name__}."
457
- )
458
- if connects_to is not None:
459
- valid_types = (str, list, tuple, set)
460
- if not isinstance(connects_to, valid_types):
461
- raise TypeError(
462
- err_message +
463
- f"`connects_to` must be one of {valid_types}, got type {type(connects_to).__name__}."
464
- )
465
- if isinstance(connects_to, (list, tuple, set)):
466
- invalid_elems = [f"{type(e).__name__}" for e in connects_to if not isinstance(e, str)]
467
- if invalid_elems:
468
- raise TypeError(
469
- err_message +
470
- f"All elements in `connects_to` must be strings, "
471
- f"but found element types: {invalid_elems}."
472
- )
473
-
474
-
475
- _validate_decorators_signature()
476
-
477
266
  for metric_handler in leap_binder.setup_container.metrics:
478
267
  if metric_handler.metric_handler_data.name == name:
479
268
  raise Exception(f'Metric with name {name} already exists. '
480
269
  f'Please choose another')
481
270
 
482
271
  def _validate_input_args(*args, **kwargs) -> None:
483
- assert len(args) > 0, (
484
- f"{user_function.__name__}() validation failed: "
485
- f"Expected at least one positional|key-word argument of type np.ndarray, "
486
- f"but received none. "
487
- f"Correct usage example: tensorleap_custom_metric(input_array: np.ndarray, ...)"
488
- )
489
272
  for i, arg in enumerate(args):
490
273
  assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
491
- f'{user_function.__name__}() validation failed: '
274
+ f'tensorleap_custom_metric validation failed: '
492
275
  f'Argument #{i} should be a numpy array. Got {type(arg)}.')
493
276
  if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
494
277
  assert arg.shape[0] == leap_binder.batch_size_to_validate, \
495
- (f'{user_function.__name__}() validation failed: Argument #{i} '
278
+ (f'tensorleap_custom_metric validation failed: Argument #{i} '
496
279
  f'first dim should be as the batch size. Got {arg.shape[0]} '
497
280
  f'instead of {leap_binder.batch_size_to_validate}')
498
281
 
499
282
  for _arg_name, arg in kwargs.items():
500
283
  assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
501
- f'{user_function.__name__}() validation failed: '
284
+ f'tensorleap_custom_metric validation failed: '
502
285
  f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
503
286
  if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
504
287
  assert arg.shape[0] == leap_binder.batch_size_to_validate, \
505
- (f'{user_function.__name__}() validation failed: Argument {_arg_name} '
288
+ (f'tensorleap_custom_metric validation failed: Argument {_arg_name} '
506
289
  f'first dim should be as the batch size. Got {arg.shape[0]} '
507
290
  f'instead of {leap_binder.batch_size_to_validate}')
508
291
 
509
292
  def _validate_result(result) -> None:
510
- validate_output_structure(result, func_name=user_function.__name__,
511
- expected_type_name="List[float | int | None | List[ConfusionMatrixElement] ] | NDArray[np.float32] or dictonary with one of these types as its values types")
512
- supported_types_message = (f'{user_function.__name__}() validation failed: '
513
- f'{user_function.__name__}() has returned unsupported type.\nSupported types are List[float|int|None], '
514
- f'List[List[ConfusionMatrixElement]], NDArray[np.float32] or dictonary with one of these types as its values types. ')
293
+ supported_types_message = (f'tensorleap_custom_metric validation failed: '
294
+ f'Metric has returned unsupported type. Supported types are List[float], '
295
+ f'List[List[ConfusionMatrixElement]], NDArray[np.float32]. ')
515
296
 
516
- def _validate_single_metric(single_metric_result,key=None):
297
+ def _validate_single_metric(single_metric_result):
517
298
  if isinstance(single_metric_result, list):
518
299
  if isinstance(single_metric_result[0], list):
519
- assert all(isinstance(cm, ConfusionMatrixElement) for cm in single_metric_result[0]), (
520
- f"{supported_types_message} "
521
- f"Got {'a dict where the value of ' + str(key) + ' is of type ' if key is not None else ''}"
522
- f"List[List[{', '.join(type(cm).__name__ for cm in single_metric_result[0])}]]."
523
- )
524
-
300
+ assert isinstance(single_metric_result[0][0], ConfusionMatrixElement), \
301
+ f'{supported_types_message}Got List[List[{type(single_metric_result[0][0])}]].'
525
302
  else:
526
- assert all(isinstance(v, (float,int,type(None),np.float32)) for v in single_metric_result), (
527
- f"{supported_types_message}\n"
528
- f"Got {'a dict where the value of ' + str(key) + ' is of type ' if key is not None else ''}"
529
- f"List[{', '.join(type(v).__name__ for v in single_metric_result)}]."
530
- )
303
+ assert isinstance(single_metric_result[0], (
304
+ float, int,
305
+ type(None))), f'{supported_types_message}Got List[{type(single_metric_result[0])}].'
531
306
  else:
532
307
  assert isinstance(single_metric_result,
533
- np.ndarray), f'{supported_types_message}\nGot {type(single_metric_result)}.'
534
- assert len(single_metric_result.shape) == 1, (f'{user_function.__name__}() validation failed: '
308
+ np.ndarray), f'{supported_types_message}Got {type(single_metric_result)}.'
309
+ assert len(single_metric_result.shape) == 1, (f'tensorleap_custom_metric validation failed: '
535
310
  f'The return shape should be 1D. Got {len(single_metric_result.shape)}D.')
536
311
 
537
312
  if leap_binder.batch_size_to_validate:
538
313
  assert len(single_metric_result) == leap_binder.batch_size_to_validate, \
539
- f'{user_function.__name__}() validation failed: The return len {f"of srt{key} value" if key is not None else ""} should be as the batch size.'
314
+ f'tensorleap_custom_metrix validation failed: The return len should be as the batch size.'
540
315
 
541
316
  if isinstance(result, dict):
542
317
  for key, value in result.items():
543
- _validate_single_metric(value,key)
544
-
545
318
  assert isinstance(key, str), \
546
- (f'{user_function.__name__}() validation failed: '
319
+ (f'tensorleap_custom_metric validation failed: '
547
320
  f'Keys in the return dict should be of type str. Got {type(key)}.')
548
321
  _validate_single_metric(value)
549
322
 
550
323
  if isinstance(direction, dict):
551
324
  for direction_key in direction:
552
325
  assert direction_key in result, \
553
- (f'{user_function.__name__}() validation failed: '
326
+ (f'tensorleap_custom_metric validation failed: '
554
327
  f'Keys in the direction mapping should be part of result keys. Got key {direction_key}.')
555
328
 
556
329
  if compute_insights is not None:
557
330
  assert isinstance(compute_insights, dict), \
558
- (f'{user_function.__name__}() validation failed: '
331
+ (f'tensorleap_custom_metric validation failed: '
559
332
  f'compute_insights should be dict if using the dict results. Got {type(compute_insights)}.')
560
333
 
561
334
  for ci_key in compute_insights:
562
335
  assert ci_key in result, \
563
- (f'{user_function.__name__}() validation failed: '
336
+ (f'tensorleap_custom_metric validation failed: '
564
337
  f'Keys in the compute_insights mapping should be part of result keys. Got key {ci_key}.')
565
338
 
566
339
  else:
@@ -568,7 +341,7 @@ def tensorleap_custom_metric(name: str,
568
341
 
569
342
  if compute_insights is not None:
570
343
  assert isinstance(compute_insights, bool), \
571
- (f'{user_function.__name__}() validation failed: '
344
+ (f'tensorleap_custom_metric validation failed: '
572
345
  f'compute_insights should be boolean. Got {type(compute_insights)}.')
573
346
 
574
347
  @functools.wraps(user_function)
@@ -600,7 +373,6 @@ def tensorleap_custom_metric(name: str,
600
373
  result = inner_without_validate(*args, **kwargs)
601
374
 
602
375
  _validate_result(result)
603
- _update_env_status("tensorleap_custom_metric","v")
604
376
  return result
605
377
 
606
378
  def mapping_inner(*args, **kwargs):
@@ -640,38 +412,28 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
640
412
  name_to_unique_name = defaultdict(set)
641
413
 
642
414
  def decorating_function(user_function: VisualizerCallableInterface):
643
- assert isinstance(visualizer_type,LeapDataType),(f"{user_function.__name__} validation failed: "
644
- f"visualizer_type should be of type {LeapDataType.__name__} but got {type(visualizer_type)}"
645
- )
646
-
647
415
  for viz_handler in leap_binder.setup_container.visualizers:
648
416
  if viz_handler.visualizer_handler_data.name == name:
649
417
  raise Exception(f'Visualizer with name {name} already exists. '
650
418
  f'Please choose another')
651
419
 
652
420
  def _validate_input_args(*args, **kwargs):
653
- assert len(args) > 0, (
654
- f"{user_function.__name__}() validation failed: "
655
- f"Expected at least one positional|key-word argument of type np.ndarray, "
656
- f"but received none. "
657
- f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
658
- )
659
421
  for i, arg in enumerate(args):
660
422
  assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
661
- f'{user_function.__name__}() validation failed: '
423
+ f'tensorleap_custom_visualizer validation failed: '
662
424
  f'Argument #{i} should be a numpy array. Got {type(arg)}.')
663
425
  if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
664
426
  assert arg.shape[0] != leap_binder.batch_size_to_validate, \
665
- (f'{user_function.__name__}() validation failed: '
427
+ (f'tensorleap_custom_visualizer validation failed: '
666
428
  f'Argument #{i} should be without batch dimension. ')
667
429
 
668
430
  for _arg_name, arg in kwargs.items():
669
431
  assert isinstance(arg, (np.ndarray, SamplePreprocessResponse)), (
670
- f'{user_function.__name__}() validation failed: '
432
+ f'tensorleap_custom_visualizer validation failed: '
671
433
  f'Argument {_arg_name} should be a numpy array. Got {type(arg)}.')
672
434
  if leap_binder.batch_size_to_validate and isinstance(arg, np.ndarray):
673
435
  assert arg.shape[0] != leap_binder.batch_size_to_validate, \
674
- (f'{user_function.__name__}() validation failed: Argument {_arg_name} '
436
+ (f'tensorleap_custom_visualizer validation failed: Argument {_arg_name} '
675
437
  f'should be without batch dimension. ')
676
438
 
677
439
  def _validate_result(result):
@@ -685,11 +447,8 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
685
447
  LeapDataType.ImageWithBBox: LeapImageWithBBox,
686
448
  LeapDataType.ImageWithHeatmap: LeapImageWithHeatmap
687
449
  }
688
- validate_output_structure(result, func_name=user_function.__name__,
689
- expected_type_name=result_type_map[visualizer_type])
690
-
691
450
  assert isinstance(result, result_type_map[visualizer_type]), \
692
- (f'{user_function.__name__}() validation failed: '
451
+ (f'tensorleap_custom_visualizer validation failed: '
693
452
  f'The return type should be {result_type_map[visualizer_type]}. Got {type(result)}.')
694
453
 
695
454
  @functools.wraps(user_function)
@@ -721,7 +480,6 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
721
480
  result = inner_without_validate(*args, **kwargs)
722
481
 
723
482
  _validate_result(result)
724
- _update_env_status("tensorleap_custom_visualizer","v")
725
483
  return result
726
484
 
727
485
  def mapping_inner(*args, **kwargs):
@@ -763,26 +521,30 @@ def tensorleap_metadata(
763
521
  f'Please choose another')
764
522
 
765
523
  def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
524
+ assert isinstance(sample_id, (int, str)), \
525
+ (f'tensorleap_metadata validation failed: '
526
+ f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
527
+ assert isinstance(preprocess_response, PreprocessResponse), \
528
+ (f'tensorleap_metadata validation failed: '
529
+ f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
766
530
  assert type(sample_id) == preprocess_response.sample_id_type, \
767
- (f'{user_function.__name__}() validation failed: '
531
+ (f'tensorleap_metadata validation failed: '
768
532
  f'Argument sample_id should be as the same type as defined in the preprocess response '
769
533
  f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
770
534
 
771
535
  def _validate_result(result):
772
536
  supported_result_types = (type(None), int, str, bool, float, dict, np.floating,
773
537
  np.bool_, np.unsignedinteger, np.signedinteger, np.integer)
774
- validate_output_structure(result, func_name=user_function.__name__,
775
- expected_type_name=supported_result_types)
776
538
  assert isinstance(result, supported_result_types), \
777
- (f'{user_function.__name__}() validation failed: '
539
+ (f'tensorleap_metadata validation failed: '
778
540
  f'Unsupported return type. Got {type(result)}. should be any of {str(supported_result_types)}')
779
541
  if isinstance(result, dict):
780
542
  for key, value in result.items():
781
543
  assert isinstance(key, str), \
782
- (f'{user_function.__name__}() validation failed: '
544
+ (f'tensorleap_metadata validation failed: '
783
545
  f'Keys in the return dict should be of type str. Got {type(key)}.')
784
546
  assert isinstance(value, supported_result_types), \
785
- (f'{user_function.__name__}() validation failed: '
547
+ (f'tensorleap_metadata validation failed: '
786
548
  f'Values in the return dict should be of type {str(supported_result_types)}. Got {type(value)}.')
787
549
 
788
550
  def inner_without_validate(sample_id, preprocess_response):
@@ -799,18 +561,15 @@ def tensorleap_metadata(
799
561
 
800
562
  leap_binder.set_metadata(inner_without_validate, name, metadata_type)
801
563
 
802
- def inner(*args,**kwargs):
564
+ def inner(sample_id, preprocess_response):
803
565
  if os.environ.get(mapping_runtime_mode_env_var_mame):
804
566
  return None
805
- validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
806
- func_name=user_function.__name__, expected_names=["idx", "preprocess"],**kwargs)
807
- sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
567
+
808
568
  _validate_input_args(sample_id, preprocess_response)
809
569
 
810
570
  result = inner_without_validate(sample_id, preprocess_response)
811
571
 
812
572
  _validate_result(result)
813
- _update_env_status("tensorleap_metadata","v")
814
573
  return result
815
574
 
816
575
  return inner
@@ -873,23 +632,19 @@ def tensorleap_preprocess():
873
632
 
874
633
  def _validate_input_args(*args, **kwargs):
875
634
  assert len(args) == 0 and len(kwargs) == 0, \
876
- (f'{user_function.__name__}() validation failed: '
635
+ (f'tensorleap_preprocess validation failed: '
877
636
  f'The function should not take any arguments. Got {args} and {kwargs}.')
878
637
 
879
638
  def _validate_result(result):
880
- assert isinstance(result, list), (
881
- f"{user_function.__name__}() validation failed: expected return type list[{PreprocessResponse.__name__}]"
882
- f"(e.g., [PreprocessResponse1, PreprocessResponse2, ...]), but returned type is {type(result).__name__}."
883
- if not isinstance(result, tuple)
884
- else f"{user_function.__name__}() validation failed: expected to return a single list[{PreprocessResponse.__name__}] object, "
885
- f"but returned {len(result)} objects instead."
886
- )
639
+ assert isinstance(result, list), \
640
+ (f'tensorleap_preprocess validation failed: '
641
+ f'The return type should be a list. Got {type(result)}.')
887
642
  for i, response in enumerate(result):
888
643
  assert isinstance(response, PreprocessResponse), \
889
- (f'{user_function.__name__}() validation failed: '
644
+ (f'tensorleap_preprocess validation failed: '
890
645
  f'Element #{i} in the return list should be a PreprocessResponse. Got {type(response)}.')
891
646
  assert len(set(result)) == len(result), \
892
- (f'{user_function.__name__}() validation failed: '
647
+ (f'tensorleap_preprocess validation failed: '
893
648
  f'The return list should not contain duplicate PreprocessResponse objects.')
894
649
 
895
650
  def inner(*args, **kwargs):
@@ -897,9 +652,9 @@ def tensorleap_preprocess():
897
652
  return [None, None, None, None]
898
653
 
899
654
  _validate_input_args(*args, **kwargs)
655
+
900
656
  result = user_function()
901
657
  _validate_result(result)
902
- _update_env_status("tensorleap_preprocess", "v")
903
658
  return result
904
659
 
905
660
  return inner
@@ -1098,23 +853,29 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1098
853
  raise Exception(f"Channel dim for input {name} is expected to be either -1 or positive")
1099
854
 
1100
855
  def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
856
+ assert isinstance(sample_id, (int, str)), \
857
+ (f'tensorleap_input_encoder validation failed: '
858
+ f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
859
+ assert isinstance(preprocess_response, PreprocessResponse), \
860
+ (f'tensorleap_input_encoder validation failed: '
861
+ f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
1101
862
  assert type(sample_id) == preprocess_response.sample_id_type, \
1102
- (f'{user_function.__name__}() validation failed: '
863
+ (f'tensorleap_input_encoder validation failed: '
1103
864
  f'Argument sample_id should be as the same type as defined in the preprocess response '
1104
865
  f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
1105
866
 
1106
867
  def _validate_result(result):
1107
- validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray")
1108
868
  assert isinstance(result, np.ndarray), \
1109
- (f'{user_function.__name__}() validation failed: '
869
+ (f'tensorleap_input_encoder validation failed: '
1110
870
  f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
1111
871
  assert result.dtype == np.float32, \
1112
- (f'{user_function.__name__}() validation failed: '
872
+ (f'tensorleap_input_encoder validation failed: '
1113
873
  f'The return type should be a numpy array of type float32. Got {result.dtype}.')
1114
- assert channel_dim - 1 <= len(result.shape), (f'{user_function.__name__}() validation failed: '
874
+ assert channel_dim - 1 <= len(result.shape), (f'tensorleap_input_encoder validation failed: '
1115
875
  f'The channel_dim ({channel_dim}) should be <= to the rank of the resulting input rank ({len(result.shape)}).')
1116
876
 
1117
877
  def inner_without_validate(sample_id, preprocess_response):
878
+
1118
879
  global _called_from_inside_tl_decorator
1119
880
  _called_from_inside_tl_decorator += 1
1120
881
 
@@ -1128,10 +889,7 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1128
889
  leap_binder.set_input(inner_without_validate, name, channel_dim=channel_dim)
1129
890
 
1130
891
 
1131
- def inner(*args, **kwargs):
1132
- validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
1133
- func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
1134
- sample_id, preprocess_response = args if len(args)!=0 else kwargs.values()
892
+ def inner(sample_id, preprocess_response):
1135
893
  _validate_input_args(sample_id, preprocess_response)
1136
894
 
1137
895
  result = inner_without_validate(sample_id, preprocess_response)
@@ -1139,19 +897,24 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1139
897
  _validate_result(result)
1140
898
 
1141
899
  if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
1142
- batch_warning(result,user_function.__name__)
1143
900
  result = np.expand_dims(result, axis=0)
1144
- _update_env_status("tensorleap_input_encoder", "v")
901
+ # Emit integration test event once per test
902
+ _emit_integration_event_once('input_encoder_integration_test', {
903
+ 'encoder_name': name,
904
+ 'channel_dim': channel_dim,
905
+ 'model_input_index': model_input_index
906
+ })
1145
907
 
1146
908
  return result
1147
909
 
1148
910
 
911
+
1149
912
  node_mapping_type = NodeMappingType.Input
1150
913
  if model_input_index is not None:
1151
914
  node_mapping_type = NodeMappingType(f'Input{str(model_input_index)}')
1152
915
  inner.node_mapping = NodeMapping(name, node_mapping_type)
1153
916
 
1154
- def mapping_inner(*args, **kwargs):
917
+ def mapping_inner(sample_id, preprocess_response):
1155
918
  class TempMapping:
1156
919
  pass
1157
920
 
@@ -1163,11 +926,11 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1163
926
 
1164
927
  mapping_inner.node_mapping = NodeMapping(name, node_mapping_type)
1165
928
 
1166
- def final_inner(*args, **kwargs):
929
+ def final_inner(sample_id, preprocess_response):
1167
930
  if os.environ.get(mapping_runtime_mode_env_var_mame):
1168
- return mapping_inner(*args, **kwargs)
931
+ return mapping_inner(sample_id, preprocess_response)
1169
932
  else:
1170
- return inner(*args, **kwargs)
933
+ return inner(sample_id, preprocess_response)
1171
934
 
1172
935
  final_inner.node_mapping = NodeMapping(name, node_mapping_type)
1173
936
 
@@ -1184,18 +947,23 @@ def tensorleap_gt_encoder(name: str):
1184
947
  f'Please choose another')
1185
948
 
1186
949
  def _validate_input_args(sample_id: Union[int, str], preprocess_response: PreprocessResponse):
950
+ assert isinstance(sample_id, (int, str)), \
951
+ (f'tensorleap_gt_encoder validation failed: '
952
+ f'Argument sample_id should be either int or str. Got {type(sample_id)}.')
953
+ assert isinstance(preprocess_response, PreprocessResponse), \
954
+ (f'tensorleap_gt_encoder validation failed: '
955
+ f'Argument preprocess_response should be a PreprocessResponse. Got {type(preprocess_response)}.')
1187
956
  assert type(sample_id) == preprocess_response.sample_id_type, \
1188
- (f'{user_function.__name__}() validation failed: '
957
+ (f'tensorleap_gt_encoder validation failed: '
1189
958
  f'Argument sample_id should be as the same type as defined in the preprocess response '
1190
959
  f'{preprocess_response.sample_id_type}. Got {type(sample_id)}.')
1191
960
 
1192
961
  def _validate_result(result):
1193
- validate_output_structure(result, func_name=user_function.__name__, expected_type_name = "np.ndarray",gt_flag=True)
1194
962
  assert isinstance(result, np.ndarray), \
1195
- (f'{user_function.__name__}() validation failed: '
963
+ (f'tensorleap_gt_encoder validation failed: '
1196
964
  f'Unsupported return type. Should be a numpy array. Got {type(result)}.')
1197
965
  assert result.dtype == np.float32, \
1198
- (f'{user_function.__name__}() validation failed: '
966
+ (f'tensorleap_gt_encoder validation failed: '
1199
967
  f'The return type should be a numpy array of type float32. Got {result.dtype}.')
1200
968
 
1201
969
  def inner_without_validate(sample_id, preprocess_response):
@@ -1212,10 +980,7 @@ def tensorleap_gt_encoder(name: str):
1212
980
  leap_binder.set_ground_truth(inner_without_validate, name)
1213
981
 
1214
982
 
1215
- def inner(*args, **kwargs):
1216
- validate_args_structure(*args, types_order=[Union[int, str], PreprocessResponse],
1217
- func_name=user_function.__name__, expected_names=["idx", "preprocess"], **kwargs)
1218
- sample_id, preprocess_response = args
983
+ def inner(sample_id, preprocess_response):
1219
984
  _validate_input_args(sample_id, preprocess_response)
1220
985
 
1221
986
  result = inner_without_validate(sample_id, preprocess_response)
@@ -1223,15 +988,13 @@ def tensorleap_gt_encoder(name: str):
1223
988
  _validate_result(result)
1224
989
 
1225
990
  if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
1226
- batch_warning(result, user_function.__name__)
1227
991
  result = np.expand_dims(result, axis=0)
1228
- _update_env_status("tensorleap_gt_encoder", "v")
1229
992
 
1230
993
  return result
1231
994
 
1232
995
  inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
1233
996
 
1234
- def mapping_inner(*args, **kwargs):
997
+ def mapping_inner(sample_id, preprocess_response):
1235
998
  class TempMapping:
1236
999
  pass
1237
1000
 
@@ -1242,11 +1005,11 @@ def tensorleap_gt_encoder(name: str):
1242
1005
 
1243
1006
  mapping_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
1244
1007
 
1245
- def final_inner(*args, **kwargs):
1008
+ def final_inner(sample_id, preprocess_response):
1246
1009
  if os.environ.get(mapping_runtime_mode_env_var_mame):
1247
- return mapping_inner(*args, **kwargs)
1010
+ return mapping_inner(sample_id, preprocess_response)
1248
1011
  else:
1249
- return inner(*args, **kwargs)
1012
+ return inner(sample_id, preprocess_response)
1250
1013
 
1251
1014
  final_inner.node_mapping = NodeMapping(name, NodeMappingType.GroundTruth)
1252
1015
 
@@ -1267,37 +1030,28 @@ def tensorleap_custom_loss(name: str, connects_to=None):
1267
1030
  valid_types = (np.ndarray, SamplePreprocessResponse)
1268
1031
 
1269
1032
  def _validate_input_args(*args, **kwargs):
1270
- assert len(args) > 0 and len(kwargs)==0, (
1271
- f"{user_function.__name__}() validation failed: "
1272
- f"Expected at least one positional|key-word argument of the allowed types (np.ndarray|SamplePreprocessResponse|list(np.ndarray|SamplePreprocessResponse)). "
1273
- f"but received none. "
1274
- f"Correct usage example: {user_function.__name__}(input_array: np.ndarray, ...)"
1275
- )
1276
1033
  for i, arg in enumerate(args):
1277
1034
  if isinstance(arg, list):
1278
1035
  for y, elem in enumerate(arg):
1279
- assert isinstance(elem, valid_types), (f'{user_function.__name__}() validation failed: '
1036
+ assert isinstance(elem, valid_types), (f'tensorleap_custom_loss validation failed: '
1280
1037
  f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
1281
1038
  else:
1282
- assert isinstance(arg, valid_types), (f'{user_function.__name__}() validation failed: '
1039
+ assert isinstance(arg, valid_types), (f'tensorleap_custom_loss validation failed: '
1283
1040
  f'Argument #{i} should be a numpy array. Got {type(arg)}.')
1284
1041
  for _arg_name, arg in kwargs.items():
1285
1042
  if isinstance(arg, list):
1286
1043
  for y, elem in enumerate(arg):
1287
- assert isinstance(elem, valid_types), (f'{user_function.__name__}() validation failed: '
1044
+ assert isinstance(elem, valid_types), (f'tensorleap_custom_loss validation failed: '
1288
1045
  f'Element #{y} of list should be a numpy array. Got {type(elem)}.')
1289
1046
  else:
1290
- assert isinstance(arg, valid_types), (f'{user_function.__name__}() validation failed: '
1047
+ assert isinstance(arg, valid_types), (f'tensorleap_custom_loss validation failed: '
1291
1048
  f'Argument #{_arg_name} should be a numpy array. Got {type(arg)}.')
1292
1049
 
1293
1050
  def _validate_result(result):
1294
- validate_output_structure(result, func_name=user_function.__name__,
1295
- expected_type_name="np.ndarray")
1296
1051
  assert isinstance(result, np.ndarray), \
1297
- (f'{user_function.__name__} validation failed: '
1052
+ (f'tensorleap_custom_loss validation failed: '
1298
1053
  f'The return type should be a numpy array. Got {type(result)}.')
1299
- assert result.ndim<2 ,(f'{user_function.__name__} validation failed: '
1300
- f'The return type should be a 1Dim numpy array but got {result.ndim}Dim.')
1054
+
1301
1055
 
1302
1056
  @functools.wraps(user_function)
1303
1057
  def inner_without_validate(*args, **kwargs):
@@ -1328,8 +1082,6 @@ def tensorleap_custom_loss(name: str, connects_to=None):
1328
1082
  result = inner_without_validate(*args, **kwargs)
1329
1083
 
1330
1084
  _validate_result(result)
1331
- _update_env_status("tensorleap_custom_loss", "v")
1332
-
1333
1085
  return result
1334
1086
 
1335
1087
  def mapping_inner(*args, **kwargs):
@@ -1386,87 +1138,3 @@ def tensorleap_custom_layer(name: str):
1386
1138
  return custom_layer
1387
1139
 
1388
1140
  return decorating_function
1389
-
1390
-
1391
- def tensorleap_status_table():
1392
- '''
1393
- Usage example:
1394
- ###################
1395
- leap_integration.py
1396
- ###################
1397
- from code_loader.inner_leap_binder.leapbinder_decorators import tensorleap_status_table
1398
- ...
1399
- ...
1400
- ...
1401
- if __name__ == '__main__':
1402
- tensorleap_status_table()
1403
- ...
1404
- '''
1405
- import atexit
1406
- import sys
1407
- import traceback
1408
-
1409
-
1410
- table = [
1411
- {"name": "tensorleap_preprocess", "status": "x"},
1412
- {"name": "tensorleap_integration_test", "status": "x"},
1413
- {"name": "tensorleap_input_encoder", "status": "x"},
1414
- {"name": "tensorleap_gt_encoder", "status": "x"},
1415
- {"name": "tensorleap_load_model", "status": "x"},
1416
- {"name": "tensorleap_custom_loss", "status": "x"},
1417
- {"name": "tensorleap_custom_metric (optional)", "status": "x"},
1418
- {"name": "tensorleap_metadata (optional)", "status": "x"},
1419
- {"name": "tensorleap_custom_visualizer (optional)", "status": "x"},
1420
-
1421
- ]
1422
-
1423
- _finalizer_called = {"done": False}
1424
-
1425
- def _print_table():
1426
- ready_mess = "\nAll parts have been successfully set. If no errors accured, you can now push the project to the Tensorleap system."
1427
- not_ready_mess = "\nSome mandatory components have not been set yet. Recommended next implementation step: "
1428
- 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 implementation step: "
1429
-
1430
- name_width = max(len(row["name"]) for row in table)
1431
- status_width = max(len(row["status"]) for row in table)
1432
- header = f"{'Function Name'.ljust(name_width)} | {'Status'.ljust(status_width)}"
1433
- sep = "-" * len(header)
1434
- print("\n" + header)
1435
- print(sep)
1436
- ready=True
1437
- for row in table:
1438
- print(f"{row['name'].ljust(name_width)} | {row['status'].ljust(status_width)}")
1439
- if row['status']=='x' and ready:
1440
- ready=False
1441
- next_step=row['name']
1442
-
1443
-
1444
- print(ready_mess) if ready else print(mandatory_ready_mess+next_step) if "optional" in next_step else print(not_ready_mess+next_step)
1445
- def update_env_params(name: str, status: str = "✓"):
1446
- for row in table:
1447
- if row["name"].removesuffix(" (optional)") == name:
1448
- row["status"] = status
1449
- break
1450
- def run_on_exit():
1451
- if _finalizer_called["done"]:
1452
- return
1453
- _finalizer_called["done"] = True
1454
- _print_table()
1455
- def handle_exception(exc_type, exc_value, exc_traceback):
1456
- traceback.print_exception(exc_type, exc_value, exc_traceback)
1457
- run_on_exit()
1458
- atexit.register(run_on_exit)
1459
- sys.excepthook = handle_exception
1460
- global _update_env_status
1461
- _update_env_status = update_env_params
1462
- return update_env_params
1463
-
1464
-
1465
-
1466
-
1467
-
1468
-
1469
-
1470
-
1471
-
1472
-
@@ -126,6 +126,43 @@ class MixpanelTracker:
126
126
  except Exception as e:
127
127
  pass
128
128
 
129
+ def track_integration_test_event(self, event_name: str, event_properties: Optional[Dict[str, Any]] = None) -> None:
130
+ """Track an integration test event with device identification.
131
+
132
+ Args:
133
+ event_name: The name of the event to track
134
+ event_properties: Optional additional properties to include in the event
135
+ """
136
+ # Skip tracking if IS_TENSORLEAP_PLATFORM environment variable is set to 'true'
137
+ if os.environ.get('IS_TENSORLEAP_PLATFORM') == 'true':
138
+ return
139
+
140
+ try:
141
+ distinct_id = self._get_distinct_id()
142
+
143
+ tensorleap_user_id = self._get_tensorleap_user_id()
144
+ whoami = self._get_whoami()
145
+ device_id = self._get_or_create_device_id()
146
+
147
+ properties = {
148
+ 'tracking_version': TRACKING_VERSION,
149
+ 'service': 'code-loader',
150
+ 'whoami': whoami,
151
+ '$device_id': device_id, # Always use device_id for $device_id
152
+ 'python_version': f"{sys.version_info.major}.{sys.version_info.minor}.{sys.version_info.micro}",
153
+ 'platform': os.name,
154
+ }
155
+
156
+ if tensorleap_user_id:
157
+ properties['user_id'] = tensorleap_user_id
158
+
159
+ if event_properties:
160
+ properties.update(event_properties)
161
+
162
+ self.mp.track(distinct_id, event_name, properties)
163
+ except Exception as e:
164
+ pass
165
+
129
166
 
130
167
  # Global tracker instance
131
168
  _tracker = None
@@ -140,3 +177,7 @@ def get_tracker() -> MixpanelTracker:
140
177
 
141
178
  def track_code_loader_loaded(event_properties: Optional[Dict[str, Any]] = None) -> None:
142
179
  get_tracker().track_code_loader_loaded(event_properties)
180
+
181
+
182
+ def track_integration_test_event(event_name: str, event_properties: Optional[Dict[str, Any]] = None) -> None:
183
+ get_tracker().track_integration_test_event(event_name, event_properties)
@@ -1,9 +1,9 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: code-loader
3
- Version: 1.0.139.dev2
3
+ Version: 1.0.139.dev4
4
4
  Summary:
5
- Home-page: https://github.com/tensorleap/code-loader
6
5
  License: MIT
6
+ License-File: LICENSE
7
7
  Author: dorhar
8
8
  Author-email: doron.harnoy@tensorleap.ai
9
9
  Requires-Python: >=3.8,<3.13
@@ -20,6 +20,7 @@ Requires-Dist: numpy (>=2.3.2,<3.0.0) ; python_version >= "3.11" and python_vers
20
20
  Requires-Dist: psutil (>=5.9.5,<6.0.0)
21
21
  Requires-Dist: pyyaml (>=6.0.2,<7.0.0)
22
22
  Requires-Dist: requests (>=2.32.3,<3.0.0)
23
+ Project-URL: Homepage, https://github.com/tensorleap/code-loader
23
24
  Project-URL: Repository, https://github.com/tensorleap/code-loader
24
25
  Description-Content-Type: text/markdown
25
26
 
@@ -1,7 +1,6 @@
1
- LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
2
1
  code_loader/__init__.py,sha256=outxRQ0M-zMfV0QGVJmAed5qWfRmyD0TV6-goEGAzBw,406
3
2
  code_loader/contract/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- code_loader/contract/datasetclasses.py,sha256=hkHMU1upWzVWkjIBoU3r14XPDleicif4Oia2xfuHgvQ,9395
3
+ code_loader/contract/datasetclasses.py,sha256=u0gfDDy02skhFG3ejJOxqxCnykhAcBPGJfv8Bi4s9eQ,8966
5
4
  code_loader/contract/enums.py,sha256=GEFkvUMXnCNt-GOoz7NJ9ecQZ2PPDettJNOsxsiM0wk,1622
6
5
  code_loader/contract/exceptions.py,sha256=jWqu5i7t-0IG0jGRsKF4DjJdrsdpJjIYpUkN1F4RiyQ,51
7
6
  code_loader/contract/mapping.py,sha256=sWJhpng-IkOzQnWQdMT5w2ZZ3X1Z_OOzSwCLXIS7oxE,1446
@@ -21,17 +20,17 @@ code_loader/experiment_api/utils.py,sha256=XZHtxge12TS4H4-8PjV3sKuhp8Ud6ojAiIzTZ
21
20
  code_loader/experiment_api/workingspace_config_utils.py,sha256=DLzXQCg4dgTV_YgaSbeTVzq-2ja_SQw4zi7LXwKL9cY,990
22
21
  code_loader/inner_leap_binder/__init__.py,sha256=koOlJyMNYzGbEsoIbXathSmQ-L38N_pEXH_HvL7beXU,99
23
22
  code_loader/inner_leap_binder/leapbinder.py,sha256=Q3D9yVM-GNEJfYRFvMV__BoZbcWOgnWKhrZXAv6Tu7o,33232
24
- code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=NlH8W1q8kVAik81EJ9ZNjWkAm8XPSW-XrKh9wBgd5BA,69593
23
+ code_loader/inner_leap_binder/leapbinder_decorators.py,sha256=ViiEBEOtpsAu2tELbxAYo1xG1ArMwbCxJhKRNuFW0sM,52704
25
24
  code_loader/leaploader.py,sha256=6D6xZzMI6qSNIb3tuKLB3BbK5H8QS1_r7iQjIXO3OkM,29795
26
25
  code_loader/leaploaderbase.py,sha256=LIFcC6xo6V_iiGN3BjibXETu_l84EWM_WIOKAvkfTiM,4458
27
- code_loader/mixpanel_tracker.py,sha256=l9z_szKKQ7apEbdNZpGH1TKAiT_TsBHb9AQnePaWTyo,4942
26
+ code_loader/mixpanel_tracker.py,sha256=ZXUD2xfd8l16fLHGGzenbGLlkneKxWm0FQrEyl4boDc,6660
28
27
  code_loader/plot_functions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
29
28
  code_loader/plot_functions/plot_functions.py,sha256=VyVWxd7R3lALIo2z8oZlYybbN0Ip6G0OiKNTNZ77xHk,14557
30
29
  code_loader/plot_functions/visualize.py,sha256=gsBAYYkwMh7jIpJeDMPS8G4CW-pxwx6LznoQIvi4vpo,657
31
30
  code_loader/utils.py,sha256=gXENTYpjdidq2dx0gVbXlErPeHoNs-4TYAZbLRe0y2c,2712
32
31
  code_loader/visualizers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
33
32
  code_loader/visualizers/default_visualizers.py,sha256=onRnLE_TXfgLN4o52hQIOOhUcFexGlqJ3xSpQDVLuZM,2604
34
- code_loader-1.0.139.dev2.dist-info/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
35
- code_loader-1.0.139.dev2.dist-info/METADATA,sha256=bZ4R5F5wQdWZEg666Lxiw1LxHcqUCmRXsgKvxFUGof4,1095
36
- code_loader-1.0.139.dev2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
37
- code_loader-1.0.139.dev2.dist-info/RECORD,,
33
+ code_loader-1.0.139.dev4.dist-info/METADATA,sha256=gNB4PI6pbmRFlmIL-baSXmhfCOaa9bXowQoTXcRrjSA,1129
34
+ code_loader-1.0.139.dev4.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
35
+ code_loader-1.0.139.dev4.dist-info/licenses/LICENSE,sha256=qIwWjdspQeSMTtnFZBC8MuT-95L02FPvzRUdWFxrwJY,1067
36
+ code_loader-1.0.139.dev4.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.9.1
2
+ Generator: poetry-core 2.2.1
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2021 TensorLeap
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.