learning-loop-node 0.18.2__py3-none-any.whl → 0.18.4__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.
Files changed (52) hide show
  1. learning_loop_node/detector/detector_node.py +2 -7
  2. learning_loop_node/detector/rest/detect.py +1 -6
  3. learning_loop_node/helpers/gdrive_downloader.py +0 -0
  4. {learning_loop_node-0.18.2.dist-info → learning_loop_node-0.18.4.dist-info}/METADATA +31 -36
  5. {learning_loop_node-0.18.2.dist-info → learning_loop_node-0.18.4.dist-info}/RECORD +15 -59
  6. {learning_loop_node-0.18.2.dist-info → learning_loop_node-0.18.4.dist-info}/WHEEL +2 -1
  7. learning_loop_node-0.18.4.dist-info/top_level.txt +1 -0
  8. learning_loop_node/examples/novelty_score_updater.py +0 -70
  9. learning_loop_node/tests/__init__.py +0 -0
  10. learning_loop_node/tests/annotator/__init__.py +0 -0
  11. learning_loop_node/tests/annotator/conftest.py +0 -55
  12. learning_loop_node/tests/annotator/pytest.ini +0 -10
  13. learning_loop_node/tests/annotator/test_annotator_node.py +0 -60
  14. learning_loop_node/tests/detector/__init__.py +0 -0
  15. learning_loop_node/tests/detector/conftest.py +0 -174
  16. learning_loop_node/tests/detector/inbox_filter/__init__.py +0 -0
  17. learning_loop_node/tests/detector/inbox_filter/test_observation.py +0 -31
  18. learning_loop_node/tests/detector/inbox_filter/test_relevance_group.py +0 -162
  19. learning_loop_node/tests/detector/inbox_filter/test_unexpected_observations_count.py +0 -35
  20. learning_loop_node/tests/detector/pytest.ini +0 -10
  21. learning_loop_node/tests/detector/test.jpg +0 -0
  22. learning_loop_node/tests/detector/test_client_communication.py +0 -177
  23. learning_loop_node/tests/detector/test_detector_node.py +0 -98
  24. learning_loop_node/tests/detector/test_outbox.py +0 -77
  25. learning_loop_node/tests/detector/test_relevance_filter.py +0 -43
  26. learning_loop_node/tests/detector/testing_detector.py +0 -28
  27. learning_loop_node/tests/general/__init__.py +0 -0
  28. learning_loop_node/tests/general/conftest.py +0 -68
  29. learning_loop_node/tests/general/pytest.ini +0 -10
  30. learning_loop_node/tests/general/test_data/file_1.txt +0 -1
  31. learning_loop_node/tests/general/test_data/file_2.txt +0 -1
  32. learning_loop_node/tests/general/test_data/model.json +0 -6
  33. learning_loop_node/tests/general/test_data_classes.py +0 -22
  34. learning_loop_node/tests/general/test_downloader.py +0 -84
  35. learning_loop_node/tests/general/test_learning_loop_node.py +0 -20
  36. learning_loop_node/tests/test_helper.py +0 -96
  37. learning_loop_node/tests/trainer/__init__.py +0 -0
  38. learning_loop_node/tests/trainer/conftest.py +0 -101
  39. learning_loop_node/tests/trainer/pytest.ini +0 -10
  40. learning_loop_node/tests/trainer/state_helper.py +0 -22
  41. learning_loop_node/tests/trainer/states/__init__.py +0 -0
  42. learning_loop_node/tests/trainer/states/test_state_cleanup.py +0 -27
  43. learning_loop_node/tests/trainer/states/test_state_detecting.py +0 -83
  44. learning_loop_node/tests/trainer/states/test_state_download_train_model.py +0 -67
  45. learning_loop_node/tests/trainer/states/test_state_prepare.py +0 -55
  46. learning_loop_node/tests/trainer/states/test_state_sync_confusion_matrix.py +0 -117
  47. learning_loop_node/tests/trainer/states/test_state_train.py +0 -65
  48. learning_loop_node/tests/trainer/states/test_state_upload_detections.py +0 -164
  49. learning_loop_node/tests/trainer/states/test_state_upload_model.py +0 -88
  50. learning_loop_node/tests/trainer/test_errors.py +0 -45
  51. learning_loop_node/tests/trainer/test_trainer_states.py +0 -39
  52. learning_loop_node/tests/trainer/testing_trainer_logic.py +0 -94
@@ -6,15 +6,10 @@ import subprocess
6
6
  import sys
7
7
  from dataclasses import asdict
8
8
  from datetime import datetime
9
- from typing import Dict, List, Optional
9
+ from typing import Dict, List, Literal, Optional
10
10
 
11
11
  import numpy as np
12
12
 
13
- try:
14
- from typing import Literal
15
- except ImportError: # Python <= 3.8
16
- from typing_extensions import Literal # type: ignore
17
-
18
13
  import socketio
19
14
  from dacite import from_dict
20
15
  from fastapi.encoders import jsonable_encoder
@@ -220,7 +215,7 @@ class DetectorNode(Node):
220
215
  max_http_buffer_size=64 * 1024 * 1024, # 64 MiB
221
216
  )
222
217
  # Initialize and mount the ASGI app
223
- self.sio_app = socketio.ASGIApp(self.sio, socketio_path='/socket.io')
218
+ self.sio_app = socketio.ASGIApp(self.sio, socketio_path='/ws/socket.io')
224
219
  self.mount('/ws', self.sio_app)
225
220
  # Register event handlers
226
221
 
@@ -1,10 +1,5 @@
1
1
  import logging
2
- from typing import TYPE_CHECKING, Optional
3
-
4
- try:
5
- from typing import Literal
6
- except ImportError: # Python <= 3.8
7
- from typing_extensions import Literal # type: ignore
2
+ from typing import TYPE_CHECKING, Literal, Optional
8
3
 
9
4
  from fastapi import APIRouter, File, Header, Request, UploadFile
10
5
 
File without changes
@@ -1,42 +1,38 @@
1
- Metadata-Version: 2.1
2
- Name: learning-loop-node
3
- Version: 0.18.2
1
+ Metadata-Version: 2.4
2
+ Name: learning_loop_node
3
+ Version: 0.18.4
4
4
  Summary: Python Library for Nodes which connect to the Zauberzeug Learning Loop
5
- Home-page: https://github.com/zauberzeug/learning_loop_node
5
+ Author-email: Zauberzeug GmbH <info@zauberzeug.com>
6
6
  License: MIT
7
- Author: Zauberzeug GmbH
8
- Author-email: info@zauberzeug.com
9
- Requires-Python: >=3.8,<4.0
10
- Classifier: License :: OSI Approved :: MIT License
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.8
13
- Classifier: Programming Language :: Python :: 3.9
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Programming Language :: Python :: 3.11
16
- Requires-Dist: Pillow (>=10.0.0,<11.0.0)
17
- Requires-Dist: aiofiles (>=0.7.0,<0.8.0)
18
- Requires-Dist: aiohttp (>=3.8.4,<4.0.0)
19
- Requires-Dist: async_generator (>=1.10,<2.0)
20
- Requires-Dist: dacite (>=1.8.1,<2.0.0)
21
- Requires-Dist: fastapi (>=0.93,<0.109)
22
- Requires-Dist: fastapi-socketio (>=0.0.10,<0.0.11)
23
- Requires-Dist: fastapi-utils (>=0.2.1,<0.3.0)
24
- Requires-Dist: httpx (>=0.28.1,<0.29.0)
25
- Requires-Dist: icecream (>=2.1.0,<3.0.0)
26
- Requires-Dist: numpy (>=1.13.3,<2.0.0)
27
- Requires-Dist: psutil (>=5.8.0,<6.0.0)
28
- Requires-Dist: pynvml (>=11.4.1,<12.0.0)
29
- Requires-Dist: pytest-mock (==3.6.1)
30
- Requires-Dist: pytest-watch (>=4.2.0,<5.0.0)
31
- Requires-Dist: python-multipart (>=0.0.5,<0.0.6)
32
- Requires-Dist: python-socketio (>=5.7.2,<6.0.0)
33
- Requires-Dist: requests (>=2.25.1,<3.0.0)
34
- Requires-Dist: simplejson (>=3.17.2,<4.0.0)
35
- Requires-Dist: tqdm (>=4.63.0,<5.0.0)
36
- Requires-Dist: uvicorn[standard] (>=0.22.0,<0.23.0)
37
- Requires-Dist: werkzeug (>=2.0.1,<3.0.0)
38
7
  Project-URL: Repository, https://github.com/zauberzeug/learning_loop_node
8
+ Requires-Python: >=3.9
39
9
  Description-Content-Type: text/markdown
10
+ Requires-Dist: fastapi<1.0,>=0.128
11
+ Requires-Dist: uvicorn[standard]<0.23.0,>=0.22.0
12
+ Requires-Dist: fastapi-utils<0.9.0,>=0.8.0
13
+ Requires-Dist: requests<3.0.0,>=2.25.1
14
+ Requires-Dist: python-socketio<6.0.0,>=5.7.2
15
+ Requires-Dist: simplejson<4.0.0,>=3.17.2
16
+ Requires-Dist: icecream<3.0.0,>=2.1.0
17
+ Requires-Dist: aiofiles<0.8.0,>=0.7.0
18
+ Requires-Dist: async_generator<2.0.0,>=1.10
19
+ Requires-Dist: pytest-watch<5.0.0,>=4.2.0
20
+ Requires-Dist: python-multipart<0.0.19,>=0.0.18
21
+ Requires-Dist: psutil<6.0.0,>=5.8.0
22
+ Requires-Dist: numpy<3.0,>=2.0
23
+ Requires-Dist: Pillow<12.0.0,>=11.0.0
24
+ Requires-Dist: tqdm<5.0.0,>=4.66.3
25
+ Requires-Dist: pytest-mock<4.0.0,>=3.6.1
26
+ Requires-Dist: pynvml<12.0.0,>=11.4.1
27
+ Requires-Dist: aiohttp<4.0.0,>=3.13.3
28
+ Requires-Dist: httpx<0.29.0,>=0.28.1
29
+ Requires-Dist: dacite<2.0.0,>=1.8.1
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest-flakefinder<2.0.0,>=1.1.0; extra == "dev"
32
+ Requires-Dist: retry<0.10.0,>=0.9.2; extra == "dev"
33
+ Requires-Dist: debugpy<2.0.0,>=1.6.7.post1; extra == "dev"
34
+ Requires-Dist: pytest-asyncio<0.22.0,>=0.21.1; extra == "dev"
35
+ Requires-Dist: autopep8<3.0.0,>=2.0.2; extra == "dev"
40
36
 
41
37
  # Learning Loop Node
42
38
 
@@ -280,4 +276,3 @@ After a short time the converted model should be available as well.
280
276
  - Nodes add properties to `model.json`, which contains all the information which are needed by subsequent nodes. These are typically the properties:
281
277
  - `resolution`: resolution in which the model expects images (as `int`, since the resolution is mostly square - later, ` resolution_x`` resolution_y ` would also be conceivable or `resolutions` to give a list of possible resolutions)
282
278
  - `categories`: list of categories with name, id, (later also type), in the order in which they are used by the model -- this is neccessary to be robust about renamings
283
-
@@ -1,4 +1,10 @@
1
1
  learning_loop_node/__init__.py,sha256=onN5s8-x_xBsCM6NLmJO0Ym1sJHeCFaGw8qb0oQZmz8,364
2
+ learning_loop_node/data_exchanger.py,sha256=nd9JNPLn9amIeTcSIyUPpbE97ORAcb5yNphvmpgWSUQ,9095
3
+ learning_loop_node/globals.py,sha256=tgw_8RYOipPV9aYlyUhYtXfUxvJKRvfUk6u-qVAtZmY,174
4
+ learning_loop_node/loop_communication.py,sha256=d1tJZ9T_y22FrEq1XzvidgH6d-byGxFq3ovLvPBS4FA,7611
5
+ learning_loop_node/node.py,sha256=xK-xODRo7ov-dNNMcpLW2GAauvjKAK3K9RQh4P9S994,12160
6
+ learning_loop_node/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ learning_loop_node/rest.py,sha256=5X9IVW9kf1gNf8jifGW9g_gI_-9TEeoMMOW16jvwpRE,1599
2
8
  learning_loop_node/annotation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
9
  learning_loop_node/annotation/annotator_logic.py,sha256=BTaopkJZkIf1CI5lfsVKsxbxoUIbDJrevavuQUT5e_c,1000
4
10
  learning_loop_node/annotation/annotator_node.py,sha256=J5xwSnM5rwTWrTe-TI37J0JHKf_4PlDuABaHvgjYr_Q,4443
@@ -10,19 +16,18 @@ learning_loop_node/data_classes/general.py,sha256=GQ6vPEIm4qqBV4RZT_YS_dPeKMdbCK
10
16
  learning_loop_node/data_classes/image_metadata.py,sha256=4FFs89iZAfr2Jh-40QqZ_GGmJ8hl_W61eHcCqHflJLE,2293
11
17
  learning_loop_node/data_classes/socket_response.py,sha256=tIdt-oYf6ULoJIDYQCecNM9OtWR6_wJ9tL0Ksu83Vko,655
12
18
  learning_loop_node/data_classes/training.py,sha256=TybwcCDf_NUaDUaOj30lPm-7Z3Qk9XFRibEX5qIv96Y,5737
13
- learning_loop_node/data_exchanger.py,sha256=nd9JNPLn9amIeTcSIyUPpbE97ORAcb5yNphvmpgWSUQ,9095
14
19
  learning_loop_node/detector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
20
  learning_loop_node/detector/detector_logic.py,sha256=8J70Fulrhex9IHFBAGYLR3a0-W-zsNj4h7mYLnrmUqM,2899
16
- learning_loop_node/detector/detector_node.py,sha256=KtrlbB4sCwtP9cy6M-Qx0dHYKXYdt_6HagNUbVo6GG0,31925
21
+ learning_loop_node/detector/detector_node.py,sha256=g1moqT-d6I6pNv7XKweUT47P4QY53XdwRme_qXYFrBc,31805
17
22
  learning_loop_node/detector/exceptions.py,sha256=C6KbNPlSbtfgDrZx2Hbhm7Suk9jVoR3fMRCO0CkrMsQ,196
23
+ learning_loop_node/detector/outbox.py,sha256=6F0MjFM-zNX-xWP_YGbmU0UYuyb0odsX_OcAxMPSzS0,12288
18
24
  learning_loop_node/detector/inbox_filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
25
  learning_loop_node/detector/inbox_filter/cam_observation_history.py,sha256=slPGm87TbBCfDUdpRTAM5yOz1An8Br5X_2HFJOGSrFg,3540
20
26
  learning_loop_node/detector/inbox_filter/relevance_filter.py,sha256=81XQV6HST2hSH-In7VF8B4BfubgUdRHTLcc16VLjUxc,1518
21
- learning_loop_node/detector/outbox.py,sha256=6F0MjFM-zNX-xWP_YGbmU0UYuyb0odsX_OcAxMPSzS0,12288
22
27
  learning_loop_node/detector/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
28
  learning_loop_node/detector/rest/about.py,sha256=evHJ2svUZY_DFz0FSef5u9c5KW4Uc3GL7EbPinG9-dg,583
24
29
  learning_loop_node/detector/rest/backdoor_controls.py,sha256=ZNaFOvC0OLWNtcLiG-NIqS_y1kkLP4csgk3CHhp8Gis,885
25
- learning_loop_node/detector/rest/detect.py,sha256=kHYX0STznMVs4UcOer_doxNeLz1xpSpBMFU-q4Em8cY,2720
30
+ learning_loop_node/detector/rest/detect.py,sha256=BHcQbSuC1sYHRKl2wNchiasb3A4HJk9tVia11e9TS6Y,2597
26
31
  learning_loop_node/detector/rest/model_version_control.py,sha256=P4FOG0U9HT6QtCoNt-1s1pT6drtgdVjGZWEuCAyuNmA,1370
27
32
  learning_loop_node/detector/rest/operation_mode.py,sha256=1_xfutA_6nzdb4Q_jZiHQ5m_wA83bcG5jSIy-sfNIvk,1575
28
33
  learning_loop_node/detector/rest/outbox_mode.py,sha256=H8coDNbgLGEfXmKQrhtXWeUHBAHpnrdZktuHXQz0xis,1148
@@ -32,8 +37,6 @@ learning_loop_node/enums/annotator.py,sha256=mtTAw-8LJIrHcYkBjYHCZuhYEEHS6QzSK8k
32
37
  learning_loop_node/enums/detector.py,sha256=Qvm5LWWR9BfsDxHEQ8YzaPaUuSmp4BescYuV4X4ikwE,512
33
38
  learning_loop_node/enums/general.py,sha256=OSpcIpdFjuRByON2xBoiIXl1SgDREIqkwnaxkTFjnHU,164
34
39
  learning_loop_node/enums/trainer.py,sha256=VaD63guLO4aKgVfXT0EryPlXKQGegSET3Cp4R0uC_Ew,746
35
- learning_loop_node/examples/novelty_score_updater.py,sha256=1DRgM9lxjFV-q2JvGDDsNLz_ic_rhEZ9wc6ZdjcxwPE,2038
36
- learning_loop_node/globals.py,sha256=tgw_8RYOipPV9aYlyUhYtXfUxvJKRvfUk6u-qVAtZmY,174
37
40
  learning_loop_node/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
38
41
  learning_loop_node/helpers/background_tasks.py,sha256=sbbS8JO1ls0ZCbNW68KOT9QLOFyFoJRXwwAq78iOmoA,3256
39
42
  learning_loop_node/helpers/environment_reader.py,sha256=6DxDJecLHxiGczByhyVa_JssAwwft7vuNCGaEzoSY2I,1662
@@ -41,65 +44,18 @@ learning_loop_node/helpers/gdrive_downloader.py,sha256=zeYJciTAJVRpu_eFjwgYLCpIa
41
44
  learning_loop_node/helpers/log_conf.py,sha256=hqVAa_9NnYEU6N0dcOKmph82p7MpgKqeF_eomTLYzWY,961
42
45
  learning_loop_node/helpers/misc.py,sha256=bHIYeOoX_5FA1qhcNlG7_kVgVXDF5jipByDwTvs8Huw,8407
43
46
  learning_loop_node/helpers/run.py,sha256=_uox-j3_K_bL3yCAwy3JYSOiIxrnhzVxyxWpCe8_J9U,876
44
- learning_loop_node/loop_communication.py,sha256=d1tJZ9T_y22FrEq1XzvidgH6d-byGxFq3ovLvPBS4FA,7611
45
- learning_loop_node/node.py,sha256=xK-xODRo7ov-dNNMcpLW2GAauvjKAK3K9RQh4P9S994,12160
46
- learning_loop_node/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- learning_loop_node/rest.py,sha256=5X9IVW9kf1gNf8jifGW9g_gI_-9TEeoMMOW16jvwpRE,1599
48
- learning_loop_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
- learning_loop_node/tests/annotator/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
- learning_loop_node/tests/annotator/conftest.py,sha256=b_J3Br5RzKl6BTeH9vfqq9Z6Th3OM_GpuGsfVxl4dlg,2100
51
- learning_loop_node/tests/annotator/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
52
- learning_loop_node/tests/annotator/test_annotator_node.py,sha256=OgdUj0PEWSe0KPTNVVi-1d7DoK7IC9Q3Q3G8TPiP9f4,2090
53
- learning_loop_node/tests/detector/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
- learning_loop_node/tests/detector/conftest.py,sha256=KMB4vXqKtmpp_wuGVyWyjVexeTOwHBtL5rnonUXq1mU,5379
55
- learning_loop_node/tests/detector/inbox_filter/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
- learning_loop_node/tests/detector/inbox_filter/test_observation.py,sha256=k4WYdvnuV7d_r7zI4M2aA8WuBjm0aycQ0vj1rGE2q4w,1370
57
- learning_loop_node/tests/detector/inbox_filter/test_relevance_group.py,sha256=r-wABFQVsTNTjv7vYGr8wbHfOWy43F_B14ZDWHfiZ-A,7613
58
- learning_loop_node/tests/detector/inbox_filter/test_unexpected_observations_count.py,sha256=A42gUuw4M2tg00ExFWg8kxhr6zT3l7t2H-tiO60QaNM,1746
59
- learning_loop_node/tests/detector/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
60
- learning_loop_node/tests/detector/test.jpg,sha256=msA-vHPmvPiro_D102Qmn1fn4vNfooqYYEXPxZUmYpk,161390
61
- learning_loop_node/tests/detector/test_client_communication.py,sha256=rMKQGckHfAg4kZf4b4IvzhAXjv9vDHyMNii-eimvVXY,8143
62
- learning_loop_node/tests/detector/test_detector_node.py,sha256=AeQkXR5BN2KiqCPIMLEfkssBMlhTW0N3YdPxpYvEz7M,3402
63
- learning_loop_node/tests/detector/test_outbox.py,sha256=Glc7TvaYnjebQ1RNstMlwOA_I60CftgbxP1U7-7GuMg,2702
64
- learning_loop_node/tests/detector/test_relevance_filter.py,sha256=pFDC262QgRUrhQmXFswiCDD9Fh2NK13lmQVCBpelF8s,2115
65
- learning_loop_node/tests/detector/testing_detector.py,sha256=ZheFZFbdmNH6jW1tQLvNHy9xJjw_vsMpWRK7cJPQvNM,742
66
- learning_loop_node/tests/general/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
67
- learning_loop_node/tests/general/conftest.py,sha256=kEtkuVA2wgny-YBkLDn7Ff5j6ShOPghQUU0cH9IIl_8,2430
68
- learning_loop_node/tests/general/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
69
- learning_loop_node/tests/general/test_data/file_1.txt,sha256=Lis06nfvbFPVCBZyEgQlfI_Nle2YDq1GQBlYvEfFtxw,19
70
- learning_loop_node/tests/general/test_data/file_2.txt,sha256=Xp8EETGhZBdVAgb4URowSSpOytwwwJdV0Renkdur7R8,19
71
- learning_loop_node/tests/general/test_data/model.json,sha256=_xNDucGOWila8gWnu8yFfrqmQ45Xq-_39eLKzjRtvpE,516
72
- learning_loop_node/tests/general/test_data_classes.py,sha256=RnDzRtB-eRfWnaaA6qAzC1W8wurFzJ4xt1Q5pd7ZCS0,721
73
- learning_loop_node/tests/general/test_downloader.py,sha256=y4GcUyR0OAfrwltd6eyQgopwTt3DwjzX0Sr8yrooLec,3347
74
- learning_loop_node/tests/general/test_learning_loop_node.py,sha256=SZd-VChpWnnsPN46pr4E_LL3ZevYx6psU-AWdVeOFpQ,770
75
- learning_loop_node/tests/test_helper.py,sha256=Qj_jS0xVOnwZvSJjUkrDxRXFe93hSi0RdG0wAlDVguo,3379
76
- learning_loop_node/tests/trainer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
- learning_loop_node/tests/trainer/conftest.py,sha256=eJUUBVRTmwcEooEN29hIa3eNuo0ogAPNn7Vqs9FSRDM,3660
78
- learning_loop_node/tests/trainer/pytest.ini,sha256=8QdjmawLy1zAzXrJ88or1kpFDhJw0W5UOnDfGGs_igU,262
79
- learning_loop_node/tests/trainer/state_helper.py,sha256=MDe9opeKruip74FoRFff8MSWGiQNFqDpPtIEIbgPnFc,919
80
- learning_loop_node/tests/trainer/states/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
- learning_loop_node/tests/trainer/states/test_state_cleanup.py,sha256=gZNxSSwnj9f0esExNnQzqadM6-sE3IsF5sNbD0bZNu8,1250
82
- learning_loop_node/tests/trainer/states/test_state_detecting.py,sha256=y3WCOqe4LPH4Rf97x7MmybbHOBwEqS3oOxg0TxScSX8,3720
83
- learning_loop_node/tests/trainer/states/test_state_download_train_model.py,sha256=-T8iAutBliv0MV5bV5lPvn2aNjF3vMBCj8iAZTC-Q7g,2992
84
- learning_loop_node/tests/trainer/states/test_state_prepare.py,sha256=boCU93Bv2VWbW73MC_suTbwCcuR7RWn-6dgVvdiJ9tA,2291
85
- learning_loop_node/tests/trainer/states/test_state_sync_confusion_matrix.py,sha256=R3UqQJ2GQMapwRQ5WuZJb9M5IfroD2QqFI4h8etiH0Y,5223
86
- learning_loop_node/tests/trainer/states/test_state_train.py,sha256=ovRs8EepQjy0yQJssK0TdcZcraBhmUkbMWeNKdHS114,2893
87
- learning_loop_node/tests/trainer/states/test_state_upload_detections.py,sha256=oFQGTeRZhW7MBISAfpe65KphZNxFUsZu3-5hD9_LS6k,7438
88
- learning_loop_node/tests/trainer/states/test_state_upload_model.py,sha256=jHWLa48tNljZwIiqI-1z71ENRGnn7Z0BsVcDBVWVBj4,3642
89
- learning_loop_node/tests/trainer/test_errors.py,sha256=LdIky-SuR4Owml8FlByD0GXdv3vGh6JuqDQgJfFdgkw,2102
90
- learning_loop_node/tests/trainer/test_trainer_states.py,sha256=OFrHSjpTIcwDp-QRe8sdseTZr0Z5dVeCt_ani9pfCqI,1238
91
- learning_loop_node/tests/trainer/testing_trainer_logic.py,sha256=vaz7EbsVRcSMyAfEGpXgNFj1yQc9dYLCYDrjjmYTZ1o,3765
92
47
  learning_loop_node/trainer/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
93
48
  learning_loop_node/trainer/downloader.py,sha256=AIyEKM4XYtd6VgmXrP3VayV9DpJzdURK1Brx81ePNSM,1470
94
49
  learning_loop_node/trainer/exceptions.py,sha256=vbuoE6kssLQuA8zd3LiDHmZglP6E2IJJwEi5AZtWXxY,420
95
50
  learning_loop_node/trainer/executor.py,sha256=XQ1TwgOF2pQv7bgzSaljDWG4I1ySjYXL8r9c_p9MX1Q,3947
96
51
  learning_loop_node/trainer/io_helpers.py,sha256=ZnAPVqhq8XCHe1NoiOQJ_w0B-estcc8CBQHnb423UDw,7226
97
- learning_loop_node/trainer/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
98
- learning_loop_node/trainer/rest/backdoor_controls.py,sha256=ZnK8ypY5r_q0-YZbtaOxhQThzuZvMsQHM5gJGESd_dE,5131
99
52
  learning_loop_node/trainer/test_executor.py,sha256=6BVGDN_6f5GEMMEvDLSG1yzMybSvgXaP5uYpSfsVPP0,2224
100
53
  learning_loop_node/trainer/trainer_logic.py,sha256=eK-01qZzi10UjLMCQX8vy5eW2FoghPj3rzzDC-s3Si4,8792
101
54
  learning_loop_node/trainer/trainer_logic_generic.py,sha256=KcHmXr-Hp8_Wuejzj8odY6sRPqi6aw1SEXv3YlbjM98,27057
102
55
  learning_loop_node/trainer/trainer_node.py,sha256=tsAMzJewdS7Bi_1b9FwG0d2lGlv2lY37pgOLWr0bP_I,4582
103
- learning_loop_node-0.18.2.dist-info/METADATA,sha256=pDPv1j1iyt9KCziZNt3WHzAgqXykLeMPnO7Yb2lqf2A,15225
104
- learning_loop_node-0.18.2.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
105
- learning_loop_node-0.18.2.dist-info/RECORD,,
56
+ learning_loop_node/trainer/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
+ learning_loop_node/trainer/rest/backdoor_controls.py,sha256=ZnK8ypY5r_q0-YZbtaOxhQThzuZvMsQHM5gJGESd_dE,5131
58
+ learning_loop_node-0.18.4.dist-info/METADATA,sha256=V9kzX_sICIu_uGtGUYzFJT8UYxkcyVPJ63LCkW0jzJA,15017
59
+ learning_loop_node-0.18.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
60
+ learning_loop_node-0.18.4.dist-info/top_level.txt,sha256=nS5qiFc4stVF_VXVCVJxZnrqVOv3IGX5-_E3sLby6OE,19
61
+ learning_loop_node-0.18.4.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: poetry-core 1.6.0
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ learning_loop_node
@@ -1,70 +0,0 @@
1
- import asyncio
2
- import logging
3
- import os
4
- from typing import Dict
5
-
6
- from tqdm import tqdm
7
-
8
- from learning_loop_node.loop_communication import LoopCommunicator
9
-
10
- os.environ['LOOP_HOST'] = 'preview.learning-loop.ai'
11
- os.environ['LOOP_ORGANIZATION'] = 'zauberzeug'
12
- os.environ['LOOP_PROJECT'] = 'demo'
13
-
14
- logging.info('Starting novelty_score_updater')
15
- glc = LoopCommunicator()
16
-
17
- project_path = f'/{glc.organization}/projects/{glc.project}'
18
-
19
-
20
- async def get_json_async(path) -> Dict:
21
- url = f'{project_path}{path}'
22
- response = await glc.get(url)
23
- if response.status_code != 200:
24
- raise Exception('bad response: ' + str(response))
25
- return response.json()
26
-
27
-
28
- def get_json(path):
29
- return asyncio.get_event_loop().run_until_complete(get_json_async(path))
30
-
31
-
32
- async def put_json_async(path, json) -> Dict:
33
- response = await glc.async_client.put(path, json=json)
34
- if response.status_code != 200:
35
- raise Exception(f'bad response: {str(response)} \n {response.json()}')
36
- return response.json()
37
-
38
-
39
- def put_json(path, json):
40
- return asyncio.get_event_loop().run_until_complete(put_json_async(path, json))
41
-
42
-
43
- data = get_json(f'{project_path}/data')
44
- categories = data['categories']
45
- image_ids = data['image_ids'][0:1] # use only one image for testing
46
- chunk_size = 50
47
-
48
- images_data = []
49
- for i in tqdm(range(0, len(image_ids), chunk_size), position=0, leave=True):
50
- chunk_ids = image_ids[i:i+chunk_size]
51
- chunk_data = get_json(f'{project_path}/images?ids={",".join(chunk_ids)}&model_version=1.1')
52
- images_data += chunk_data['images']
53
-
54
- novelty_scores = {}
55
- for image_data in images_data:
56
- image_id = image_data['id']
57
- detections = image_data['box_detections']
58
- novelty_score = 0
59
- for d in detections:
60
- if d['confidence'] > 20 and d['confidence'] < 80:
61
- novelty_score += 1
62
- novelty_scores[image_id] = novelty_score
63
-
64
-
65
- put_json('/images/novelty_scores', json=novelty_scores)
66
-
67
- loop = asyncio.get_event_loop()
68
- loop.run_until_complete(glc.shutdown())
69
-
70
- logging.info('novelty_score_updater stopped')
File without changes
File without changes
@@ -1,55 +0,0 @@
1
- import asyncio
2
- import logging
3
- import os
4
- import shutil
5
-
6
- # ====================================== REDUNDANT FIXTURES IN ALL CONFTESTS ! ======================================
7
- import sys
8
-
9
- import pytest
10
-
11
- from ...globals import GLOBALS
12
- from ...loop_communication import LoopCommunicator
13
-
14
-
15
- @pytest.fixture()
16
- async def setup_test_project(): # pylint: disable=redefined-outer-name
17
- loop_communicator = LoopCommunicator()
18
- try:
19
- await loop_communicator.delete("/zauberzeug/projects/pytest_nodelib_annotator?keep_images=true", timeout=10)
20
- except Exception:
21
- logging.exception("Failed to delete project pytest_nodelib_annotator")
22
- sys.exit(1)
23
- await asyncio.sleep(1)
24
- project_conf = {
25
- 'project_name': 'pytest_nodelib_annotator', 'inbox': 0, 'annotate': 0, 'review': 0, 'complete': 3, 'image_style': 'beautiful',
26
- 'box_categories': 2, 'point_categories': 2, 'segmentation_categories': 2, 'thumbs': False, 'tags': 0,
27
- 'trainings': 1, 'box_detections': 3, 'box_annotations': 0}
28
- assert (await loop_communicator.post("/zauberzeug/projects/generator", json=project_conf)).status_code == 200
29
- yield
30
- await loop_communicator.delete("/zauberzeug/projects/pytest_nodelib_annotator?keep_images=true", timeout=10)
31
- await loop_communicator.shutdown()
32
-
33
-
34
- @pytest.fixture(autouse=True, scope='session')
35
- def clear_loggers():
36
- """Remove handlers from all loggers"""
37
- # see https://github.com/pytest-dev/pytest/issues/5502
38
- yield
39
-
40
- loggers = [logging.getLogger()] + list(logging.Logger.manager.loggerDict.values())
41
- for logger in loggers:
42
- if not isinstance(logger, logging.Logger):
43
- continue
44
- handlers = getattr(logger, 'handlers', [])
45
- for handler in handlers:
46
- logger.removeHandler(handler)
47
-
48
-
49
- @pytest.fixture(autouse=True, scope='function')
50
- def data_folder():
51
- GLOBALS.data_folder = '/tmp/learning_loop_lib_data'
52
- shutil.rmtree(GLOBALS.data_folder, ignore_errors=True)
53
- os.makedirs(GLOBALS.data_folder, exist_ok=True)
54
- yield
55
- shutil.rmtree(GLOBALS.data_folder, ignore_errors=True)
@@ -1,10 +0,0 @@
1
- [pytest]
2
- python_files = test_*.py
3
- asyncio_mode = auto
4
-
5
- cache_dir = /tmp/pytest_cache
6
-
7
- # for debbuging tests:
8
- ; log_cli_level = INFO
9
- ; log_cli_format = %(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)
10
- ; log_cli_date_format=%Y-%m-%d %H:%M:%S
@@ -1,60 +0,0 @@
1
- import os
2
- from dataclasses import asdict
3
- from typing import Dict
4
-
5
- import pytest
6
- from fastapi.encoders import jsonable_encoder
7
-
8
- from ...annotation.annotator_logic import AnnotatorLogic
9
- from ...annotation.annotator_node import AnnotatorNode
10
- from ...data_classes import (
11
- AnnotationData,
12
- Category,
13
- Context,
14
- Point,
15
- ToolOutput,
16
- UserInput,
17
- )
18
- from ...enums import AnnotationEventType, CategoryType
19
-
20
-
21
- class MockedAnnotatatorLogic(AnnotatorLogic):
22
- async def handle_user_input(self, user_input: UserInput, history: Dict) -> ToolOutput:
23
- return ToolOutput(svg="")
24
-
25
- def create_empty_history(self) -> dict:
26
- return {}
27
-
28
- def logout_user(self, sid: str) -> bool:
29
- return True
30
-
31
-
32
- def default_user_input() -> UserInput:
33
- annotation_data = AnnotationData(
34
- coordinate=Point(x=0, y=0),
35
- event_type=AnnotationEventType.LeftMouseDown,
36
- context=Context(organization='zauberzeug', project='pytest_nodelib_annotator'),
37
- image_uuid='10f7d7d2-4076-7006-af37-fa28a6a848ae',
38
- category=Category(id='some_id', name='category_1', description='',
39
- hotkey='', color='', type=CategoryType.Segmentation)
40
- )
41
- return UserInput(frontend_id='some_id', data=annotation_data)
42
-
43
- # ------------------------------------------------------------ TESTS ------------------------------------------------------------
44
-
45
-
46
- @pytest.mark.asyncio
47
- @pytest.mark.usefixtures('setup_test_project')
48
- async def test_image_download():
49
- # pylint: disable=protected-access
50
-
51
- image_folder = '/tmp/learning_loop_lib_data/zauberzeug/pytest_nodelib_annotator/images'
52
-
53
- assert os.path.exists(image_folder) is False or len(os.listdir(image_folder)) == 0
54
-
55
- node = AnnotatorNode(name="", uuid="", annotator_logic=MockedAnnotatatorLogic())
56
- user_input = default_user_input()
57
- await node._ensure_sio_connection() # This is required as the node is not "started"
58
- _ = await node._handle_user_input(jsonable_encoder(asdict(user_input)))
59
-
60
- assert os.path.exists(image_folder) is True and len(os.listdir(image_folder)) == 1
File without changes
@@ -1,174 +0,0 @@
1
- import asyncio
2
- import logging
3
- import multiprocessing
4
- import os
5
- import shutil
6
- import socket
7
- from glob import glob
8
- from multiprocessing import Process, log_to_stderr
9
- from typing import AsyncGenerator
10
-
11
- import numpy as np
12
- import pytest
13
- import socketio
14
- import uvicorn
15
-
16
- from learning_loop_node.data_classes import BoxDetection, ImageMetadata
17
- from learning_loop_node.detector.detector_logic import DetectorLogic
18
-
19
- from ...detector.detector_node import DetectorNode
20
- from ...detector.outbox import Outbox
21
- from ...globals import GLOBALS
22
- from .testing_detector import TestingDetectorLogic
23
-
24
- logging.basicConfig(level=logging.INFO)
25
-
26
- # show ouptut from uvicorn server https://stackoverflow.com/a/66132186/364388
27
- log_to_stderr(logging.INFO)
28
-
29
- detector_port = GLOBALS.detector_port
30
-
31
-
32
- def should_have_segmentations(request) -> bool:
33
- should_have_seg = False
34
- try:
35
- should_have_seg = request.param
36
- except Exception:
37
- pass
38
- return should_have_seg
39
-
40
-
41
- @pytest.fixture(scope="session", name="event_loop")
42
- def fixture_event_loop():
43
- """Overrides pytest default function scoped event loop"""
44
- policy = asyncio.get_event_loop_policy()
45
- loop = policy.new_event_loop()
46
- yield loop
47
- loop.close()
48
-
49
-
50
- @pytest.fixture()
51
- async def test_detector_node():
52
- """Initializes and runs a detector testnode. Note that the running instance and the one the function returns are not the same instances!"""
53
-
54
- os.environ['LOOP_ORGANIZATION'] = 'zauberzeug'
55
- os.environ['LOOP_PROJECT'] = 'demo'
56
-
57
- detector = TestingDetectorLogic()
58
- node = DetectorNode(name='test', detector=detector)
59
- await port_is(free=True)
60
-
61
- multiprocessing.set_start_method('fork', force=True)
62
- assert multiprocessing.get_start_method() == 'fork'
63
- # print('\n\n',multiprocessing.get_start_method())
64
-
65
- proc = Process(target=uvicorn.run,
66
- args=(node,),
67
- kwargs={
68
- "host": "127.0.0.1",
69
- "port": detector_port,
70
- }, daemon=True)
71
- proc.start()
72
- await port_is(free=False)
73
- yield node
74
-
75
- try:
76
- await node._on_shutdown() # pylint: disable=protected-access
77
- except Exception:
78
- logging.exception('error while shutting down node')
79
-
80
- try:
81
- proc.kill()
82
- except Exception: # for python 3.6
83
- proc.terminate()
84
- proc.join()
85
-
86
- # from https://stackoverflow.com/a/52872579/364388
87
-
88
-
89
- def is_port_in_use(port):
90
- with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
91
- return s.connect_ex(('localhost', port)) == 0
92
-
93
-
94
- async def port_is(free: bool):
95
- for _ in range(10):
96
- if not free and is_port_in_use(detector_port):
97
- return
98
- if free and not is_port_in_use(detector_port):
99
- return
100
- await asyncio.sleep(0.5)
101
- raise Exception(f'port {detector_port} is {"not" if free else ""} free')
102
-
103
-
104
- @pytest.fixture()
105
- async def sio_client() -> AsyncGenerator[socketio.AsyncClient, None]:
106
- sio = socketio.AsyncClient()
107
- try_connect = True
108
- retry_count = 0
109
- while try_connect:
110
- try:
111
- await sio.connect(f"ws://localhost:{detector_port}", socketio_path="/ws/socket.io")
112
- try_connect = False
113
- except Exception:
114
- logging.exception("Connection failed with error:")
115
- logging.warning('trying again')
116
- await asyncio.sleep(5)
117
- retry_count += 1
118
- if retry_count > 10:
119
- raise Exception('Max Retry')
120
-
121
- yield sio
122
- await sio.disconnect()
123
-
124
-
125
- def get_outbox_files(outbox: Outbox):
126
- files = glob(f'{outbox.path}/**/*', recursive=True)
127
- return [file for file in files if os.path.isfile(file)]
128
-
129
-
130
- class MockDetectorLogic(DetectorLogic): # pylint: disable=abstract-method
131
- def __init__(self):
132
- super().__init__('mock')
133
- self.image_metadata = ImageMetadata(
134
- box_detections=[BoxDetection(category_name="test",
135
- category_id="1",
136
- confidence=0.9,
137
- x=0, y=0, width=10, height=10,
138
- model_name="mock", )])
139
-
140
- def evaluate(self, image: np.ndarray) -> ImageMetadata:
141
- return self.image_metadata
142
-
143
-
144
- @pytest.fixture
145
- def detector_node():
146
- os.environ['LOOP_ORGANIZATION'] = 'test_organization'
147
- os.environ['LOOP_PROJECT'] = 'test_project'
148
- return DetectorNode(name="test_node", detector=MockDetectorLogic())
149
-
150
- # ====================================== REDUNDANT FIXTURES IN ALL CONFTESTS ! ======================================
151
-
152
-
153
- @pytest.fixture(autouse=True, scope='session')
154
- def clear_loggers():
155
- """Remove handlers from all loggers"""
156
- # see https://github.com/pytest-dev/pytest/issues/5502
157
- yield
158
-
159
- loggers = [logging.getLogger()] + list(logging.Logger.manager.loggerDict.values())
160
- for logger in loggers:
161
- if not isinstance(logger, logging.Logger):
162
- continue
163
- handlers = getattr(logger, 'handlers', [])
164
- for handler in handlers:
165
- logger.removeHandler(handler)
166
-
167
-
168
- @pytest.fixture(autouse=True, scope='function')
169
- def data_folder():
170
- GLOBALS.data_folder = '/tmp/learning_loop_lib_data'
171
- shutil.rmtree(GLOBALS.data_folder, ignore_errors=True)
172
- os.makedirs(GLOBALS.data_folder, exist_ok=True)
173
- yield
174
- shutil.rmtree(GLOBALS.data_folder, ignore_errors=True)
@@ -1,31 +0,0 @@
1
- import time
2
- from datetime import datetime, timedelta
3
-
4
- from ....data_classes import BoxDetection, Observation
5
-
6
-
7
- def test_aging():
8
- _detection = Observation(BoxDetection(category_name='dirt', x=10, y=0, height=30, width=100,
9
- model_name='model', confidence=0.30, category_id='some-id'))
10
- time.sleep(0.2)
11
- assert _detection.is_older_than(0.1)
12
- assert not _detection.is_older_than(0.3)
13
-
14
-
15
- def test_calculate_iou():
16
- one = BoxDetection(category_name='dirt', x=10, y=0, width=30, height=100,
17
- model_name='model', confidence=0.30, category_id='some-id')
18
- two = BoxDetection(category_name='dirt', x=20, y=0, width=30, height=100,
19
- model_name='model', confidence=0.61, category_id='some-id')
20
- three = BoxDetection(category_name='dirt', x=0, y=30, width=10, height=10,
21
- model_name='model', confidence=0.61, category_id='some-id')
22
-
23
- assert one.intersection_over_union(two) == 0.5
24
- assert one.intersection_over_union(three) == 0.0
25
-
26
-
27
- def test_update_last_seen():
28
- observation = Observation(BoxDetection(category_name='dirt', x=10, y=0, height=30,
29
- width=100, model_name='model', confidence=0.30, category_id='some-id'))
30
- observation.last_seen = datetime.now() - timedelta(seconds=.5)
31
- assert observation.is_older_than(0.5)