code-loader 1.0.143__tar.gz → 1.0.143.dev3__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.

Potentially problematic release.


This version of code-loader might be problematic. Click here for more details.

Files changed (36) hide show
  1. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/PKG-INFO +1 -1
  2. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/inner_leap_binder/leapbinder_decorators.py +38 -4
  3. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/mixpanel_tracker.py +97 -9
  4. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/plot_functions/plot_functions.py +1 -1
  5. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/pyproject.toml +2 -2
  6. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/LICENSE +0 -0
  7. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/README.md +0 -0
  8. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/__init__.py +0 -0
  9. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/__init__.py +0 -0
  10. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/datasetclasses.py +0 -0
  11. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/enums.py +0 -0
  12. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/exceptions.py +0 -0
  13. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/mapping.py +0 -0
  14. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/responsedataclasses.py +0 -0
  15. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/contract/visualizer_classes.py +0 -0
  16. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/default_losses.py +0 -0
  17. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/default_metrics.py +0 -0
  18. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/__init__.py +0 -0
  19. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/api.py +0 -0
  20. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/cli_config_utils.py +0 -0
  21. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/client.py +0 -0
  22. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/epoch.py +0 -0
  23. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/experiment.py +0 -0
  24. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/experiment_context.py +0 -0
  25. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/types.py +0 -0
  26. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/utils.py +0 -0
  27. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/experiment_api/workingspace_config_utils.py +0 -0
  28. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/inner_leap_binder/__init__.py +0 -0
  29. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/inner_leap_binder/leapbinder.py +0 -0
  30. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/leaploader.py +0 -0
  31. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/leaploaderbase.py +0 -0
  32. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/plot_functions/__init__.py +0 -0
  33. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/plot_functions/visualize.py +0 -0
  34. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/utils.py +0 -0
  35. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/code_loader/visualizers/__init__.py +0 -0
  36. {code_loader-1.0.143 → code_loader-1.0.143.dev3}/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.143
3
+ Version: 1.0.143.dev3
4
4
  Summary:
5
5
  Home-page: https://github.com/tensorleap/code-loader
6
6
  License: MIT
@@ -1,14 +1,18 @@
1
1
  # mypy: ignore-errors
2
2
  import os
3
3
  import warnings
4
+ import logging
4
5
  from collections import defaultdict
5
6
  from functools import lru_cache
6
7
  from pathlib import Path
8
+ from typing import Optional, Union, Callable, List, Dict, Set, Any
7
9
  from typing import Optional, Union, Callable, List, Dict, get_args, get_origin
8
10
 
9
11
  import numpy as np
10
12
  import numpy.typing as npt
11
13
 
14
+ logger = logging.getLogger(__name__)
15
+
12
16
  from code_loader.contract.datasetclasses import CustomCallableInterfaceMultiArgs, \
13
17
  CustomMultipleReturnCallableInterfaceMultiArgs, ConfusionMatrixCallableInterfaceMultiArgs, CustomCallableInterface, \
14
18
  VisualizerCallableInterface, MetadataSectionCallableInterface, PreprocessResponse, SectionCallableInterface, \
@@ -20,6 +24,7 @@ from code_loader.contract.mapping import NodeMapping, NodeMappingType, NodeConne
20
24
  from code_loader.contract.visualizer_classes import LeapImage, LeapImageMask, LeapTextMask, LeapText, LeapGraph, \
21
25
  LeapHorizontalBar, LeapImageWithBBox, LeapImageWithHeatmap
22
26
  from code_loader.inner_leap_binder.leapbinder import mapping_runtime_mode_env_var_mame
27
+ from code_loader.mixpanel_tracker import clear_integration_events, AnalyticsEvent, emit_integration_event_once
23
28
 
24
29
  import inspect
25
30
  import functools
@@ -172,6 +177,11 @@ def tensorleap_integration_test():
172
177
  _validate_input_args(*args, **kwargs)
173
178
 
174
179
  global _called_from_inside_tl_integration_test_decorator
180
+ # Clear integration test events for new test
181
+ try:
182
+ clear_integration_events()
183
+ except Exception as e:
184
+ logger.debug(f"Failed to clear integration events: {e}")
175
185
  try:
176
186
  _called_from_inside_tl_integration_test_decorator = True
177
187
  if not _call_from_tl_platform:
@@ -489,7 +499,7 @@ def tensorleap_custom_metric(name: str,
489
499
  f'Please choose another')
490
500
 
491
501
  def _validate_input_args(*args, **kwargs) -> None:
492
- assert len(args) > 0, (
502
+ assert len(args)+len(kwargs) > 0, (
493
503
  f"{user_function.__name__}() validation failed: "
494
504
  f"Expected at least one positional|key-word argument of type np.ndarray, "
495
505
  f"but received none. "
@@ -660,7 +670,7 @@ def tensorleap_custom_visualizer(name: str, visualizer_type: LeapDataType,
660
670
  f'Please choose another')
661
671
 
662
672
  def _validate_input_args(*args, **kwargs):
663
- assert len(args) > 0, (
673
+ assert len(args) + len(kwargs) > 0, (
664
674
  f"{user_function.__name__}() validation failed: "
665
675
  f"Expected at least one positional|key-word argument of type np.ndarray, "
666
676
  f"but received none. "
@@ -884,7 +894,7 @@ def tensorleap_preprocess():
884
894
  leap_binder.set_preprocess(user_function)
885
895
 
886
896
  def _validate_input_args(*args, **kwargs):
887
- assert len(args) == 0 and len(kwargs) == 0, \
897
+ assert len(args) + len(kwargs) > 0, \
888
898
  (f'{user_function.__name__}() validation failed: '
889
899
  f'The function should not take any arguments. Got {args} and {kwargs}.')
890
900
 
@@ -911,6 +921,14 @@ def tensorleap_preprocess():
911
921
  _validate_input_args(*args, **kwargs)
912
922
  result = user_function()
913
923
  _validate_result(result)
924
+
925
+ # Emit integration test event once per test
926
+ try:
927
+ emit_integration_event_once(AnalyticsEvent.PREPROCESS_INTEGRATION_TEST, {
928
+ 'preprocess_responses_count': len(result)
929
+ })
930
+ except Exception as e:
931
+ logger.debug(f"Failed to emit preprocess integration test event: {e}")
914
932
  if not _call_from_tl_platform:
915
933
  update_env_params_func("tensorleap_preprocess", "v")
916
934
  return result
@@ -1154,6 +1172,15 @@ def tensorleap_input_encoder(name: str, channel_dim=-1, model_input_index=None):
1154
1172
  if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
1155
1173
  batch_warning(result,user_function.__name__)
1156
1174
  result = np.expand_dims(result, axis=0)
1175
+ # Emit integration test event once per test
1176
+ try:
1177
+ emit_integration_event_once(AnalyticsEvent.INPUT_ENCODER_INTEGRATION_TEST, {
1178
+ 'encoder_name': name,
1179
+ 'channel_dim': channel_dim,
1180
+ 'model_input_index': model_input_index
1181
+ })
1182
+ except Exception as e:
1183
+ logger.debug(f"Failed to emit input_encoder integration test event: {e}")
1157
1184
  if not _call_from_tl_platform:
1158
1185
  update_env_params_func("tensorleap_input_encoder", "v")
1159
1186
 
@@ -1239,6 +1266,13 @@ def tensorleap_gt_encoder(name: str):
1239
1266
  if _called_from_inside_tl_decorator == 0 and _called_from_inside_tl_integration_test_decorator:
1240
1267
  batch_warning(result, user_function.__name__)
1241
1268
  result = np.expand_dims(result, axis=0)
1269
+ # Emit integration test event once per test
1270
+ try:
1271
+ emit_integration_event_once(AnalyticsEvent.GT_ENCODER_INTEGRATION_TEST, {
1272
+ 'encoder_name': name
1273
+ })
1274
+ except Exception as e:
1275
+ logger.debug(f"Failed to emit gt_encoder integration test event: {e}")
1242
1276
  if not _call_from_tl_platform:
1243
1277
  update_env_params_func("tensorleap_gt_encoder", "v")
1244
1278
  return result
@@ -1281,7 +1315,7 @@ def tensorleap_custom_loss(name: str, connects_to=None):
1281
1315
  valid_types = (np.ndarray, SamplePreprocessResponse)
1282
1316
 
1283
1317
  def _validate_input_args(*args, **kwargs):
1284
- assert len(args) > 0 and len(kwargs)==0, (
1318
+ assert len(args) + len(kwargs) > 0, (
1285
1319
  f"{user_function.__name__}() validation failed: "
1286
1320
  f"Expected at least one positional|key-word argument of the allowed types (np.ndarray|SamplePreprocessResponse|list(np.ndarray|SamplePreprocessResponse)). "
1287
1321
  f"but received none. "
@@ -5,12 +5,53 @@ import os
5
5
  import sys
6
6
  import getpass
7
7
  import uuid
8
- from typing import Optional, Dict, Any
8
+ import logging
9
+ from enum import Enum
10
+ from typing import Optional, Dict, Any, Set, Union, TypedDict
9
11
  import mixpanel # type: ignore[import]
10
12
 
13
+ logger = logging.getLogger(__name__)
14
+
11
15
  TRACKING_VERSION = '1'
12
16
 
13
17
 
18
+ class AnalyticsEvent(str, Enum):
19
+ """Enumeration of all tracked analytics events."""
20
+ CODE_LOADER_LOADED = "code_loader_loaded"
21
+ LOAD_MODEL_INTEGRATION_TEST = "load_model_integration_test"
22
+ PREPROCESS_INTEGRATION_TEST = "preprocess_integration_test"
23
+ INPUT_ENCODER_INTEGRATION_TEST = "input_encoder_integration_test"
24
+ GT_ENCODER_INTEGRATION_TEST = "gt_encoder_integration_test"
25
+
26
+
27
+ class CodeLoaderLoadedProps(TypedDict, total=False):
28
+ """Properties for code_loader_loaded event."""
29
+ event_type: str
30
+ code_path: str
31
+ code_entry_name: str
32
+
33
+
34
+ class LoadModelEventProps(TypedDict, total=False):
35
+ """Properties for load_model_integration_test event."""
36
+ prediction_types_count: int
37
+
38
+
39
+ class PreprocessEventProps(TypedDict, total=False):
40
+ """Properties for preprocess_integration_test event."""
41
+ preprocess_responses_count: int
42
+
43
+
44
+ class InputEncoderEventProps(TypedDict, total=False):
45
+ """Properties for input_encoder_integration_test event."""
46
+ encoder_name: str
47
+ channel_dim: int
48
+
49
+
50
+ class GtEncoderEventProps(TypedDict, total=False):
51
+ """Properties for gt_encoder_integration_test event."""
52
+ encoder_name: str
53
+
54
+
14
55
  class MixpanelTracker:
15
56
  """Handles Mixpanel event tracking for code-loader."""
16
57
 
@@ -28,7 +69,8 @@ class MixpanelTracker:
28
69
  if self._user_id is None:
29
70
  try:
30
71
  self._user_id = getpass.getuser()
31
- except Exception:
72
+ except Exception as e:
73
+ logger.debug(f"Failed to get username via getpass: {e}")
32
74
  # Fallback to environment variables or default
33
75
  self._user_id = os.environ.get('USER', os.environ.get('USERNAME', 'unknown'))
34
76
  return self._user_id or 'unknown'
@@ -43,8 +85,8 @@ class MixpanelTracker:
43
85
  user_id = f.read().strip()
44
86
  if user_id:
45
87
  return user_id
46
- except Exception:
47
- pass
88
+ except Exception as e:
89
+ logger.debug(f"Failed to read TensorLeap user ID: {e}")
48
90
  return None
49
91
 
50
92
  def _get_or_create_device_id(self) -> str:
@@ -73,7 +115,8 @@ class MixpanelTracker:
73
115
  f.write(device_id)
74
116
 
75
117
  return device_id
76
- except Exception:
118
+ except Exception as e:
119
+ logger.debug(f"Failed to read/write device ID file: {e}")
77
120
  # Fallback to generating a new UUID if file operations fail
78
121
  return str(uuid.uuid4())
79
122
 
@@ -90,10 +133,11 @@ class MixpanelTracker:
90
133
 
91
134
  return self._get_or_create_device_id()
92
135
 
93
- def track_code_loader_loaded(self, event_properties: Optional[Dict[str, Any]] = None) -> None:
94
- """Track code loader loaded event with device identification.
136
+ def _track_event(self, event_name: Union[str, AnalyticsEvent], event_properties: Optional[Dict[str, Any]] = None) -> None:
137
+ """Internal method to track any event with device identification.
95
138
 
96
139
  Args:
140
+ event_name: The name of the event to track (string or AnalyticsEvent enum)
97
141
  event_properties: Optional additional properties to include in the event
98
142
  """
99
143
  # Skip tracking if IS_TENSORLEAP_PLATFORM environment variable is set to 'true'
@@ -122,9 +166,26 @@ class MixpanelTracker:
122
166
  if event_properties:
123
167
  properties.update(event_properties)
124
168
 
125
- self.mp.track(distinct_id, 'code_loader_loaded', properties)
169
+ self.mp.track(distinct_id, str(event_name), properties)
126
170
  except Exception as e:
127
- pass
171
+ logger.debug(f"Failed to track event '{event_name}': {e}")
172
+
173
+ def track_code_loader_loaded(self, event_properties: Optional[Dict[str, Any]] = None) -> None:
174
+ """Track code loader loaded event with device identification.
175
+
176
+ Args:
177
+ event_properties: Optional additional properties to include in the event
178
+ """
179
+ self._track_event(AnalyticsEvent.CODE_LOADER_LOADED, event_properties)
180
+
181
+ def track_integration_test_event(self, event_name: Union[str, AnalyticsEvent], event_properties: Optional[Dict[str, Any]] = None) -> None:
182
+ """Track an integration test event with device identification.
183
+
184
+ Args:
185
+ event_name: The name of the event to track (string or AnalyticsEvent enum)
186
+ event_properties: Optional additional properties to include in the event
187
+ """
188
+ self._track_event(event_name, event_properties)
128
189
 
129
190
 
130
191
  # Global tracker instance
@@ -140,3 +201,30 @@ def get_tracker() -> MixpanelTracker:
140
201
 
141
202
  def track_code_loader_loaded(event_properties: Optional[Dict[str, Any]] = None) -> None:
142
203
  get_tracker().track_code_loader_loaded(event_properties)
204
+
205
+
206
+ def track_integration_test_event(event_name: Union[str, AnalyticsEvent], event_properties: Optional[Dict[str, Any]] = None) -> None:
207
+ get_tracker().track_integration_test_event(event_name, event_properties)
208
+
209
+
210
+ # Module-level set to track which integration test events have been emitted
211
+ _integration_events_emitted: Set[str] = set()
212
+
213
+
214
+ def emit_integration_event_once(event_name: Union[str, AnalyticsEvent], props: Dict[str, Any]) -> None:
215
+ """Emit an integration test event only once per test run."""
216
+ event_name_str = str(event_name)
217
+ if event_name_str in _integration_events_emitted:
218
+ return
219
+
220
+ try:
221
+ track_integration_test_event(event_name, props)
222
+ _integration_events_emitted.add(event_name_str)
223
+ except Exception as e:
224
+ logger.debug(f"Failed to emit integration event once '{event_name}': {e}")
225
+
226
+
227
+ def clear_integration_events() -> None:
228
+ """Clear the integration events set for a new test run."""
229
+ global _integration_events_emitted
230
+ _integration_events_emitted.clear()
@@ -324,7 +324,7 @@ def plot_image_mask(leap_data: LeapImageMask, title: str) -> None:
324
324
 
325
325
  # fill the instance mask with a translucent color
326
326
  overlayed_image[instance_mask] = (
327
- overlayed_image[instance_mask] * (1 - 0.5) + np.array(colors[i][:image.shape[-1]], dtype=np.uint8) * 0.5)
327
+ overlayed_image[instance_mask] * (1 - 0.5) + np.array(colors[i][:image.shape[-1]], dtype=image.dtype) * 0.5)
328
328
 
329
329
  # Display the result using matplotlib
330
330
  fig, ax = plt.subplots(1)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "code-loader"
3
- version = "1.0.143"
3
+ version = "1.0.143.dev3"
4
4
  description = ""
5
5
  authors = ["dorhar <doron.harnoy@tensorleap.ai>"]
6
6
  license = "MIT"
@@ -22,7 +22,7 @@ requests = "^2.32.3"
22
22
  pyyaml = "^6.0.2"
23
23
  mixpanel = "^4.10.0"
24
24
 
25
- [tool.poetry.dev-dependencies]
25
+ [tool.poetry.group.dev.dependencies]
26
26
  pytest = "^7.1.1"
27
27
  grappa = "^1.0.1"
28
28
  pytest-cov = "^3.0.0"