learning-loop-node 0.10.4__py3-none-any.whl → 0.10.6__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 learning-loop-node might be problematic. Click here for more details.

@@ -1,3 +1,4 @@
1
+ import asyncio
1
2
  import os
2
3
  from dataclasses import asdict
3
4
  from typing import Dict
@@ -7,10 +8,8 @@ from fastapi.encoders import jsonable_encoder
7
8
 
8
9
  from learning_loop_node.annotation.annotator_logic import AnnotatorLogic
9
10
  from learning_loop_node.annotation.annotator_node import AnnotatorNode
10
- from learning_loop_node.data_classes import (AnnotationData,
11
- AnnotationEventType, Category,
12
- CategoryType, Context, Point,
13
- ToolOutput, UserInput)
11
+ from learning_loop_node.data_classes import (AnnotationData, AnnotationEventType, Category, CategoryType, Context,
12
+ Point, ToolOutput, UserInput)
14
13
 
15
14
 
16
15
  class MockedAnnotatatorLogic(AnnotatorLogic):
@@ -29,7 +28,7 @@ def default_user_input() -> UserInput:
29
28
  coordinate=Point(x=0, y=0),
30
29
  event_type=AnnotationEventType.LeftMouseDown,
31
30
  context=Context(organization='zauberzeug', project='pytest_p'),
32
- image_uuid='501205a9-9b64-3df0-3785-507a677b7f05',
31
+ image_uuid='f786350c-89ca-9424-9b00-720a9a85fe09',
33
32
  category=Category(id='some_id', name='category_1', description='',
34
33
  hotkey='', color='', type=CategoryType.Segmentation)
35
34
  )
@@ -40,7 +39,8 @@ def default_user_input() -> UserInput:
40
39
 
41
40
  @pytest.mark.asyncio
42
41
  async def test_image_download(setup_test_project): # pylint: disable=unused-argument
43
- image_path = '/tmp/learning_loop_lib_data/zauberzeug/pytest_p/images/501205a9-9b64-3df0-3785-507a677b7f05.jpg'
42
+ # TODO: This test depends on a pseudo-random uuid..
43
+ image_path = '/tmp/learning_loop_lib_data/zauberzeug/pytest_p/images/f786350c-89ca-9424-9b00-720a9a85fe09.jpg'
44
44
 
45
45
  assert os.path.exists(image_path) is False
46
46
 
@@ -156,9 +156,6 @@ class DetectorNode(Node):
156
156
 
157
157
  tags = data.get('tags', [])
158
158
  tags.append('picked_by_system')
159
- camera_id = data.get('camera-id', None) or data.get('mac', None)
160
- if camera_id is not None:
161
- tags.append(camera_id)
162
159
 
163
160
  loop = asyncio.get_event_loop()
164
161
  try:
@@ -315,8 +312,6 @@ class DetectorNode(Node):
315
312
  n_po, n_se = len(detections.point_detections), len(detections.segmentation_detections)
316
313
  self.log.info(f'detected:{n_bo} boxes, {n_po} points, {n_se} segs, {n_cl} classes')
317
314
 
318
- if camera_id is not None:
319
- tags.append(camera_id)
320
315
  if autoupload is None or autoupload == 'filtered': # NOTE default is filtered
321
316
  Thread(target=self.relevance_filter.may_upload_detections,
322
317
  args=(detections, camera_id, raw_image, tags)).start()
@@ -44,6 +44,7 @@ async def test_executor_lifecycle():
44
44
 
45
45
  assert not executor.is_running()
46
46
  sleep(1)
47
+ # NOTE: It happend that this process became a zombie process which leads to repeated test failures -> restart machine required
47
48
  assert_process_is_running('some_executable.sh', False)
48
49
 
49
50
 
@@ -3,7 +3,7 @@ import logging
3
3
  import os
4
4
  import shlex
5
5
  from io import BufferedWriter
6
- from typing import List, Optional
6
+ from typing import List, Optional, Dict
7
7
 
8
8
 
9
9
  class Executor:
@@ -16,7 +16,7 @@ class Executor:
16
16
 
17
17
  self.path = base_path
18
18
  self.log_file_path = f'{self.path}/{log_name}'
19
- self.log_file: None | BufferedWriter = None
19
+ self.log_file: Optional[BufferedWriter] = None
20
20
  self._process: Optional[asyncio.subprocess.Process] = None # pylint: disable=no-member
21
21
  os.makedirs(self.path, exist_ok=True)
22
22
 
@@ -26,7 +26,7 @@ class Executor:
26
26
  return self._process
27
27
  return None
28
28
 
29
- async def start(self, cmd: str, env: Optional[dict[str, str]] = None) -> None:
29
+ async def start(self, cmd: str, env: Optional[Dict[str, str]] = None) -> None:
30
30
  """Start the process with the given command and environment variables."""
31
31
 
32
32
  full_env = os.environ.copy()
@@ -159,18 +159,20 @@ class ActiveTrainingIO:
159
159
  async def _upload_detections_batched(self, context: Context, detections: List[Detections]):
160
160
  batch_size = 100
161
161
  skip_detections = self.load_detection_upload_progress()
162
- up_count = 0
163
162
  for i in range(skip_detections, len(detections), batch_size):
164
- up_count += 1
165
- up_progress = i+batch_size
166
- batch_detections = detections[i:up_progress]
167
- await self._upload_detections(context, batch_detections, up_progress)
163
+ up_progress = i + batch_size if i + batch_size < len(detections) else 0
164
+ batch_detections = detections[i:i + batch_size]
165
+ await self._upload_detections_and_save_progress(context, batch_detections, up_progress)
168
166
  skip_detections = up_progress
169
167
 
170
168
  logging.info('uploaded %d detections', len(detections))
171
169
 
172
- async def _upload_detections(self, context: Context, batch_detections: List[Detections], up_progress: int):
170
+ async def _upload_detections_and_save_progress(self, context: Context, batch_detections: List[Detections], up_progress: int):
171
+ if len(batch_detections) == 0:
172
+ print('skipping empty batch', flush=True)
173
+ return
173
174
  detections_json = [jsonable_encoder(asdict(detections)) for detections in batch_detections]
175
+ print(f'uploading {len(detections_json)} detections', flush=True)
174
176
  response = await self.loop_communicator.post(
175
177
  f'/{context.organization}/projects/{context.project}/detections', json=detections_json)
176
178
  if response.status_code != 200:
@@ -179,7 +181,4 @@ class ActiveTrainingIO:
179
181
  raise Exception(msg)
180
182
 
181
183
  logging.info('successfully uploaded detections')
182
- if up_progress >= len(batch_detections):
183
- self.save_detection_upload_progress(0)
184
- else:
185
- self.save_detection_upload_progress(up_progress)
184
+ self.save_detection_upload_progress(up_progress)
@@ -29,7 +29,7 @@ async def test_initialized_trainer_node():
29
29
  trainer._node = node
30
30
  trainer._init_new_training(context=Context(organization='zauberzeug', project='demo'),
31
31
  details={'categories': [],
32
- 'id': '917d5c7f-403d-7e92-f95f-577f79c2273a', # version 1.2 of demo project
32
+ 'id': '00000000-0000-0000-0000-000000000012', # version 1.2 of demo project
33
33
  'training_number': 0,
34
34
  'resolution': 800,
35
35
  'flip_rl': False,
@@ -49,7 +49,7 @@ async def test_initialized_trainer():
49
49
  trainer._node = node
50
50
  trainer._init_new_training(context=Context(organization='zauberzeug', project='demo'),
51
51
  details={'categories': [],
52
- 'id': '917d5c7f-403d-7e92-f95f-577f79c2273a', # version 1.2 of demo project
52
+ 'id': '00000000-0000-0000-0000-000000000012', # version 1.2 of demo project
53
53
  'training_number': 0,
54
54
  'resolution': 800,
55
55
  'flip_rl': False,
@@ -14,11 +14,11 @@ def trainer_has_error(trainer: TrainerLogic):
14
14
  return trainer.errors.has_error_for(error_key)
15
15
 
16
16
 
17
- async def test_successful_detecting(test_initialized_trainer: TestingTrainerLogic): # NOTE was a flaky test
17
+ async def test_successful_detecting(test_initialized_trainer: TestingTrainerLogic):
18
18
  trainer = test_initialized_trainer
19
19
  create_active_training_file(trainer, training_state='train_model_uploaded',
20
- model_uuid_for_detecting='917d5c7f-403d-7e92-f95f-577f79c2273a')
21
- # trainer.load_active_training()
20
+ model_uuid_for_detecting='00000000-0000-0000-0000-000000000011') # NOTE: this is the hard coded model uuid for zauberzeug/demo (model version 1.1)
21
+
22
22
  _ = asyncio.get_running_loop().create_task(
23
23
  trainer._perform_state('do_detections', TrainerState.Detecting, TrainerState.Detected, trainer._do_detections))
24
24
 
@@ -37,7 +37,7 @@ async def create_valid_detection_file(trainer: TrainerLogic, number_of_entries:
37
37
  'point_detections': [], 'segmentation_detections': []})
38
38
  detections = [detection_entry] * number_of_entries
39
39
 
40
- assert trainer.active_training_io is not None # pylint: disable=protected-access
40
+ assert trainer.active_training_io is not None
41
41
  trainer.active_training_io.save_detections(detections, file_index)
42
42
 
43
43
 
@@ -80,21 +80,21 @@ async def test_ensure_all_detections_are_uploaded(test_initialized_trainer: Test
80
80
  create_active_training_file(trainer, training_state=TrainerState.Detected)
81
81
  trainer._init_from_last_training()
82
82
 
83
- await create_valid_detection_file(trainer, 2, 0)
84
- await create_valid_detection_file(trainer, 2, 1)
83
+ await create_valid_detection_file(trainer, 4, 0)
84
+ await create_valid_detection_file(trainer, 4, 1)
85
85
 
86
86
  assert trainer.active_training_io.load_detections_upload_file_index() == 0
87
87
  detections = trainer.active_training_io.load_detections(0)
88
- assert len(detections) == 2
88
+ assert len(detections) == 4
89
89
 
90
- batch_size = 1
90
+ batch_size = 2
91
91
  skip_detections = trainer.active_training_io.load_detection_upload_progress()
92
92
  for i in range(skip_detections, len(detections), batch_size):
93
93
  batch_detections = detections[i:i+batch_size]
94
- # pylint: disable=protected-access
95
- await trainer.active_training_io._upload_detections(trainer.training.context, batch_detections, i + batch_size)
94
+ progress = i + batch_size if i + batch_size < len(detections) else 0
95
+ await trainer.active_training_io._upload_detections_and_save_progress(trainer.training.context, batch_detections, progress)
96
96
 
97
- expected_value = i + batch_size if i + batch_size < len(detections) else 0 # Progress is reset for every file
97
+ expected_value = progress # Progress is reset for every file
98
98
  assert trainer.active_training_io.load_detection_upload_progress() == expected_value
99
99
 
100
100
  assert trainer.active_training_io.load_detections_upload_file_index() == 0
@@ -107,10 +107,11 @@ async def test_ensure_all_detections_are_uploaded(test_initialized_trainer: Test
107
107
  skip_detections = trainer.active_training_io.load_detection_upload_progress()
108
108
  for i in range(skip_detections, len(detections), batch_size):
109
109
  batch_detections = detections[i:i+batch_size]
110
- # pylint: disable=protected-access
111
- await trainer.active_training_io._upload_detections(trainer.training.context, batch_detections, i + batch_size)
112
110
 
113
- expected_value = i + batch_size if i + batch_size < len(detections) else 0 # Progress is reset for every file
111
+ progress = i + batch_size if i + batch_size < len(detections) else 0
112
+ await trainer.active_training_io._upload_detections_and_save_progress(trainer.training.context, batch_detections, progress)
113
+
114
+ expected_value = progress # Progress is reset for every file
114
115
  assert trainer.active_training_io.load_detection_upload_progress() == expected_value
115
116
  assert trainer.active_training_io.load_detections_upload_file_index() == 1
116
117
 
@@ -160,5 +161,5 @@ async def test_abort_uploading(test_initialized_trainer: TestingTrainerLogic):
160
161
  await trainer.stop()
161
162
  await asyncio.sleep(0.1)
162
163
 
163
- assert trainer._training is None # pylint: disable=protected-access
164
+ assert trainer._training is None
164
165
  assert trainer.node.last_training_io.exists() is False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: learning-loop-node
3
- Version: 0.10.4
3
+ Version: 0.10.6
4
4
  Summary: Python Library for Nodes which connect to the Zauberzeug Learning Loop
5
5
  Home-page: https://github.com/zauberzeug/learning_loop_node
6
6
  License: MIT
@@ -2,7 +2,7 @@ learning_loop_node/__init__.py,sha256=onN5s8-x_xBsCM6NLmJO0Ym1sJHeCFaGw8qb0oQZmz
2
2
  learning_loop_node/annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  learning_loop_node/annotation/annotator_logic.py,sha256=BTaopkJZkIf1CI5lfsVKsxbxoUIbDJrevavuQUT5e_c,1000
4
4
  learning_loop_node/annotation/annotator_node.py,sha256=wk11CQtM3A0Dr7efCn_Mw2X7ql5xn2sgEJzrIeSBC6Q,4043
5
- learning_loop_node/annotation/tests/test_annotator_node.py,sha256=yCox-ohCXOpCbcTit7PwtE4iLHud8qiZ6UOqqycwPxg,2065
5
+ learning_loop_node/annotation/tests/test_annotator_node.py,sha256=VdwM7Z0vqmwewmijmUPduo9hxZYn5y1nlFauxnjxoDs,2046
6
6
  learning_loop_node/conftest.py,sha256=Q_8Dbl3RwI8X_Y5Zvzstr6NJEqY3KldZXVx618OLdb4,3492
7
7
  learning_loop_node/data_classes/__init__.py,sha256=wCX88lDgbb8V-gtVCVe9i-NvvZuMe5FX7eD_UJgYYXw,1305
8
8
  learning_loop_node/data_classes/annotations.py,sha256=iInU0Nuy_oYT_sj4k_n-W0UShCBI2cHQYrt8imymbtM,1211
@@ -13,7 +13,7 @@ learning_loop_node/data_classes/training.py,sha256=hnMHZMk-WNRERyo7U97qL09v1tIdh
13
13
  learning_loop_node/data_exchanger.py,sha256=hxF0zANA35f5EV8tkQ4yjelrKuvafMaKUya0CCjVrK0,8221
14
14
  learning_loop_node/detector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  learning_loop_node/detector/detector_logic.py,sha256=se0jRFbV7BfTvCuCI3gcUllSYIZ5dxTkvdISe6pPTRg,1660
16
- learning_loop_node/detector/detector_node.py,sha256=k05ZXOK0OiKg4U7IMSFz-N-w1DmLvB3WF5MzMkkByP4,16776
16
+ learning_loop_node/detector/detector_node.py,sha256=BStenBbtRuvuDxg6lscxvfz_lV_Am5MAAr0bRbTP50o,16553
17
17
  learning_loop_node/detector/inbox_filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  learning_loop_node/detector/inbox_filter/cam_observation_history.py,sha256=TD346I9ymtIP0_CJXCIKMRuiXbfVVanXNu_iHAwDd7Q,3318
19
19
  learning_loop_node/detector/inbox_filter/relevance_filter.py,sha256=s2FuwZ-tD_5obkSutstjc8pE_hLGbrv9WjrEO9t8rJ8,1011
@@ -52,27 +52,27 @@ learning_loop_node/tests/test_data/file_2.txt,sha256=Xp8EETGhZBdVAgb4URowSSpOytw
52
52
  learning_loop_node/tests/test_data/model.json,sha256=_xNDucGOWila8gWnu8yFfrqmQ45Xq-_39eLKzjRtvpE,516
53
53
  learning_loop_node/tests/test_data_classes.py,sha256=m8LEk1quGErxuPzNdW_ExqQjkwE4u7ribwnTdyeiHR8,788
54
54
  learning_loop_node/tests/test_downloader.py,sha256=RkXNVQJkfPddGzxfJgSF7kc-V6Qp1OOvYYuhQ9g_ls4,2806
55
- learning_loop_node/tests/test_executor.py,sha256=-QLylzigUEoUzeQssPR3ECFkD2tWH-fsA_lEGXy993c,2119
55
+ learning_loop_node/tests/test_executor.py,sha256=DuwYv-27R0fUqkcMmIiArXhiPhDnLzgNC4vp2r6Jyj4,2250
56
56
  learning_loop_node/tests/test_helper.py,sha256=AjOrTu3dHIlJLYI0mxcNx8MCmFF6IjLhHtPzuai4O9E,2334
57
57
  learning_loop_node/tests/test_learning_loop_node.py,sha256=4qWi1ovBzebUAbvw8ecSa-TBGKYuJvlKe2AMnMZ-Qs8,701
58
58
  learning_loop_node/trainer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
59
  learning_loop_node/trainer/downloader.py,sha256=qzx7zzObcFEvRVQFe8gi8KJNIapASi1_XssbspXD1Rw,1469
60
- learning_loop_node/trainer/executor.py,sha256=j-1pkc_5b1Y0Bh8KiQthAK7SoOfJelr5Qi7L0p1sTxE,3933
61
- learning_loop_node/trainer/io_helpers.py,sha256=fyjImT1NY10gLV0KM4Ns7sRrtKFswVJU_pV9-c3IVEY,7152
60
+ learning_loop_node/trainer/executor.py,sha256=-0BxDqmAI1NCiISi7Rw8McJQfgxxVy1gSa1epYuL3U0,3942
61
+ learning_loop_node/trainer/io_helpers.py,sha256=Ylxz8HAId0Jlz95So5kXdJEp1yKQuwroDKIhbTUscF4,7257
62
62
  learning_loop_node/trainer/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
63
  learning_loop_node/trainer/rest/backdoor_controls.py,sha256=YQcG0KwxzKDNYeMtHrSwr26q__N7ty0o6Kar6CLWAd0,5869
64
64
  learning_loop_node/trainer/rest/controls.py,sha256=XF37i2edeMHKdSXyJc4ZqaTZ38u6d3u3Sb3C-Mwyfko,934
65
65
  learning_loop_node/trainer/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
66
- learning_loop_node/trainer/tests/conftest.py,sha256=UIVmnZZVe1DigOxeraiLh89cyw1QNQFvNJWmPUY1uFI,2455
66
+ learning_loop_node/trainer/tests/conftest.py,sha256=qUmcHPme19AD6K6sQektX63iZecdqPRHKQ2CVNoBzNg,2455
67
67
  learning_loop_node/trainer/tests/state_helper.py,sha256=igoGqTBqcqqFcDng2i7ctC67bYR1hLPDl4G_mNRG6r8,934
68
68
  learning_loop_node/trainer/tests/states/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
69
69
  learning_loop_node/trainer/tests/states/test_state_cleanup.py,sha256=tiL31hSjg1Bl2obzg2ufAVpil5qW0YkpDCpSHPqXQrk,1312
70
- learning_loop_node/trainer/tests/states/test_state_detecting.py,sha256=NU065RhpUwhExldGp-79YD_P9bG4O9DNcLjBfW0qmik,3811
70
+ learning_loop_node/trainer/tests/states/test_state_detecting.py,sha256=heJS9KO9GzIgFiKMvrNWPrboujY6hcR-KjztZ6fivxk,3833
71
71
  learning_loop_node/trainer/tests/states/test_state_download_train_model.py,sha256=rNRXIyqyHzHz4fXY1Lsf7WKg8FFVFYfFPIevMCBBcCY,2940
72
72
  learning_loop_node/trainer/tests/states/test_state_prepare.py,sha256=fx9_bgPTaR5ANVB8n_hW8dXcaJIh_iKEnInmhzamZ9E,2432
73
73
  learning_loop_node/trainer/tests/states/test_state_sync_confusion_matrix.py,sha256=zfNbHB3GFSJXXoEkW-8PYtmX62md3feWp4oisyzs8A4,4773
74
74
  learning_loop_node/trainer/tests/states/test_state_train.py,sha256=j1vedjH2EwLTgHhon6eR9ttp-Sw9ozR9-9QgAKlFO-M,3248
75
- learning_loop_node/trainer/tests/states/test_state_upload_detections.py,sha256=38MumBw_N6Pt5cXI8x-xZjczmWUc7BIqyw4TSfim9h4,7751
75
+ learning_loop_node/trainer/tests/states/test_state_upload_detections.py,sha256=u31gC0-Z2EVTnia1dyY2yNGDGAeyIXPfObBgrEWHhVQ,7674
76
76
  learning_loop_node/trainer/tests/states/test_state_upload_model.py,sha256=gAXJJcoxj2EVdFJcPAeqxGAjeL1a4ofLtytnM4joi-Q,3808
77
77
  learning_loop_node/trainer/tests/test_errors.py,sha256=8H-kjs9kEBoHWcQVJIZvW5zcwCs1VQI5Tf5I0VSbCUA,2245
78
78
  learning_loop_node/trainer/tests/test_trainer_states.py,sha256=OBrClH6srAM2hqqel2xTtfHCeTKYZlG_S4KO2G2GrS4,1147
@@ -80,6 +80,6 @@ learning_loop_node/trainer/tests/testing_trainer_logic.py,sha256=7sQ6okiOhM4IhvR
80
80
  learning_loop_node/trainer/trainer_logic.py,sha256=PJxiO1chPdvpq8UTtzv_nVam9CouCswX9b1FnRwT2Tw,8411
81
81
  learning_loop_node/trainer/trainer_logic_generic.py,sha256=KFDuxgzrGITHQaJoGvhjHxWzhbb4Q7HBxSpks4CeGBg,24801
82
82
  learning_loop_node/trainer/trainer_node.py,sha256=bcyOMeLXrLuLgsPqS8lwEOSZ6vCjGLgT0pLXgaylI1Q,4155
83
- learning_loop_node-0.10.4.dist-info/METADATA,sha256=bOfPBBjEdohsOEBpAD7grcYOQpo5d7akcNrbxmA3hdY,9287
84
- learning_loop_node-0.10.4.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
85
- learning_loop_node-0.10.4.dist-info/RECORD,,
83
+ learning_loop_node-0.10.6.dist-info/METADATA,sha256=fxypCq0VtpapGOz_5Ao8NhcAtN-Xp-1aQb-qGWWXM7M,9287
84
+ learning_loop_node-0.10.6.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
85
+ learning_loop_node-0.10.6.dist-info/RECORD,,