radnn 0.0.7.2__py3-none-any.whl → 0.0.8__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 (60) hide show
  1. radnn/__init__.py +7 -5
  2. radnn/core.py +44 -28
  3. radnn/data/__init__.py +8 -0
  4. radnn/data/data_feed.py +147 -0
  5. radnn/data/dataset_base.py +3 -5
  6. radnn/data/dataset_folder.py +55 -0
  7. radnn/data/image_dataset.py +0 -2
  8. radnn/data/image_dataset_files.py +175 -0
  9. radnn/data/preprocess/normalizer.py +7 -1
  10. radnn/data/preprocess/standardizer.py +9 -2
  11. radnn/data/sample_set.py +30 -17
  12. radnn/data/sequence_dataset.py +0 -2
  13. radnn/data/subset_type.py +45 -0
  14. radnn/data/tf_classification_data_feed.py +113 -0
  15. radnn/errors.py +29 -0
  16. radnn/evaluation/evaluate_classification.py +7 -3
  17. radnn/experiment/ml_experiment.py +29 -0
  18. radnn/experiment/ml_experiment_config.py +61 -32
  19. radnn/experiment/ml_experiment_env.py +6 -2
  20. radnn/experiment/ml_experiment_store.py +0 -1
  21. radnn/images/__init__.py +2 -0
  22. radnn/images/colors.py +28 -0
  23. radnn/images/image_processor.py +513 -0
  24. radnn/learn/learning_algorithm.py +4 -3
  25. radnn/ml_system.py +59 -18
  26. radnn/plots/plot_auto_multi_image.py +27 -17
  27. radnn/plots/plot_confusion_matrix.py +7 -4
  28. radnn/plots/plot_learning_curve.py +7 -3
  29. radnn/plots/plot_multi_scatter.py +7 -3
  30. radnn/plots/plot_roc.py +8 -4
  31. radnn/plots/plot_voronoi_2d.py +8 -5
  32. radnn/stats/__init__.py +1 -0
  33. radnn/stats/descriptive_stats.py +45 -0
  34. radnn/system/files/__init__.py +1 -0
  35. radnn/system/files/csvfile.py +8 -5
  36. radnn/system/files/filelist.py +40 -0
  37. radnn/system/files/fileobject.py +9 -4
  38. radnn/system/files/imgfile.py +8 -4
  39. radnn/system/files/jsonfile.py +8 -4
  40. radnn/system/files/picklefile.py +8 -4
  41. radnn/system/files/textfile.py +37 -7
  42. radnn/system/filestore.py +36 -18
  43. radnn/system/filesystem.py +8 -3
  44. radnn/system/hosts/colab_host.py +29 -0
  45. radnn/system/hosts/linux_host.py +29 -0
  46. radnn/system/hosts/windows_host.py +39 -1
  47. radnn/system/tee_logger.py +7 -3
  48. radnn/system/threads/__init__.py +5 -0
  49. radnn/system/threads/semaphore_lock.py +58 -0
  50. radnn/system/threads/thread_context.py +175 -0
  51. radnn/system/threads/thread_safe_queue.py +163 -0
  52. radnn/system/threads/thread_safe_string_collection.py +66 -0
  53. radnn/system/threads/thread_worker.py +68 -0
  54. radnn/utils.py +96 -2
  55. {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/METADATA +1 -1
  56. radnn-0.0.8.dist-info/RECORD +70 -0
  57. radnn-0.0.7.2.dist-info/RECORD +0 -53
  58. {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/LICENSE.txt +0 -0
  59. {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/WHEEL +0 -0
  60. {radnn-0.0.7.2.dist-info → radnn-0.0.8.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,10 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
1
7
  # ......................................................................................
2
- # MIT License
3
8
 
4
9
  # Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
5
10
 
@@ -20,8 +25,8 @@
20
25
  # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
26
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
27
  # SOFTWARE.
23
- # ......................................................................................
24
28
 
29
+ # .......................................................................................
25
30
  import os
26
31
  from radnn.core import system_name
27
32
  from radnn.system.filestore import FileStore
@@ -30,7 +35,7 @@ from radnn.system.files import JSONFile
30
35
  # =======================================================================================================================
31
36
  class FileSystem(object):
32
37
  # --------------------------------------------------------------------------------------------------------
33
- def __init__(self, config_folder="MLConfig", model_folder="MLModels", dataset_folder="MLData", must_exist=False, setup_filename="*auto*", is_custom_setup=False):
38
+ def __init__(self, config_folder="MLConfig", model_folder="MLModels", dataset_folder="MLData", must_exist=False, setup_filename="*auto*", is_custom_setup=True):
34
39
  '''
35
40
  Initializes the file system settings for an experiment
36
41
  :param config_folder: The folder that contains the experiment hyperparameter files.
@@ -1,3 +1,32 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
7
+ # ......................................................................................
8
+
9
+ # Copyright (c) 2019-2025 Pantelis I. Kaplanoglou
10
+
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
20
+
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ # .......................................................................................
1
30
  import os
2
31
  from google.colab import drive
3
32
  from google.colab import files
@@ -1,3 +1,32 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
7
+ # ......................................................................................
8
+
9
+ # Copyright (c) 2024-2025 Pantelis I. Kaplanoglou
10
+
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
20
+
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ # .......................................................................................
1
30
  class LinuxHost(object):
2
31
  def __init__(self):
3
32
  pass
@@ -1,5 +1,34 @@
1
- import win32api
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
7
+ # ......................................................................................
8
+
9
+ # Copyright (c) 2024-2025 Pantelis I. Kaplanoglou
10
+
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
2
20
 
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ # .......................................................................................
30
+ import win32api
31
+ import ctypes
3
32
  class WindowsHost(object):
4
33
  # --------------------------------------------------------------------------------------------------------------------
5
34
  @classmethod
@@ -38,4 +67,13 @@ class WindowsHost(object):
38
67
  str_info = u'\\StringFileInfo\\%04X%04X\\%s' % (sLanguageCode, sCodePage, sVersionString)
39
68
  dInfo[sVersionString] = repr(win32api.GetFileVersionInfo(dll_filename, str_info))
40
69
  return dInfo
70
+ # --------------------------------------------------------------------------------------------------------------------
71
+ @classmethod
72
+ def set_windows_sleep_resolution(cls, msecs=1):
73
+ """
74
+ Requests a minimum resolution for periodic timers. This increases accuracy
75
+ for the waiting interval of the time.sleep function
76
+ """
77
+ oWinMM = ctypes.WinDLL('oWinMM')
78
+ oWinMM.timeBeginPeriod(msecs)
41
79
  # --------------------------------------------------------------------------------------------------------------------
@@ -1,5 +1,10 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
1
7
  # ......................................................................................
2
- # MIT License
3
8
 
4
9
  # Copyright (c) 2024-2025 Pantelis I. Kaplanoglou
5
10
 
@@ -21,8 +26,7 @@
21
26
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22
27
  # SOFTWARE.
23
28
 
24
- # ......................................................................................
25
-
29
+ # .......................................................................................
26
30
  import os
27
31
  import sys
28
32
  from datetime import datetime
@@ -0,0 +1,5 @@
1
+ from .thread_context import ThreadContext, ThreadEx
2
+ from .thread_worker import ThreadWorker
3
+ from .semaphore_lock import SemaphoreLock
4
+ from .thread_safe_queue import ThreadSafeQueue
5
+ from .thread_safe_string_collection import ThreadSafeQueue
@@ -0,0 +1,58 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
7
+ # ......................................................................................
8
+
9
+ # Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
10
+
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
20
+
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ # .......................................................................................
30
+ from threading import BoundedSemaphore
31
+
32
+ #=======================================================================================================================
33
+ class SemaphoreLock(BoundedSemaphore):
34
+ # ------------------------------------------------------------------------------------------------------------------
35
+ def __init__(self, value=1):
36
+ super(SemaphoreLock, self).__init__(value)
37
+ # ------------------------------------------------------------------------------------------------------------------
38
+ def lock(self, blocking=True, timeout=None):
39
+ self.acquire(blocking, timeout)
40
+ # ------------------------------------------------------------------------------------------------------------------
41
+ def unlock(self):
42
+ self.release()
43
+ # ------------------------------------------------------------------------------------------------------------------
44
+ # //TODO: Not working, check if this can be fixed
45
+ '''
46
+ def __enter__(self):
47
+ self.Lock()
48
+ return self
49
+
50
+ def __exit__(self, exception_type, exception_val, trace):
51
+ try:
52
+ self.Unlock()
53
+ except:
54
+ print("Could not unlock semaphore")
55
+ return True
56
+ '''
57
+ # ------------------------------------------------------------------------------------------------------------------
58
+ #=======================================================================================================================
@@ -0,0 +1,175 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
7
+ # ......................................................................................
8
+
9
+ # Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
10
+
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
20
+
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ # .......................................................................................
30
+ import time
31
+ from threading import Thread, Event, get_ident
32
+ from datetime import datetime
33
+
34
+
35
+ #=======================================================================================================================
36
+ class ThreadEx(Thread):
37
+ # ------------------------------------------------------------------------------------------------------------------
38
+ def __init__(self,target=None, name=None, args=(), kwargs=None):
39
+ #//TODO: delegate target, args and kwargs properly
40
+ super(ThreadEx, self).__init__(target=target, name=name, args=args, kwargs=kwargs)
41
+ self._stop_event = Event()
42
+ # ------------------------------------------------------------------------------------------------------------------
43
+ def stop(self):
44
+ self._stop_event.set()
45
+ # ------------------------------------------------------------------------------------------------------------------
46
+ @property
47
+ def is_stopped(self):
48
+ return self._stop_event.is_set()
49
+ # ------------------------------------------------------------------------------------------------------------------
50
+ #=======================================================================================================================
51
+
52
+
53
+
54
+
55
+
56
+
57
+
58
+
59
+
60
+ #=======================================================================================================================
61
+ class ThreadContext(object):
62
+ __NEXT_ID = 0
63
+
64
+ # ------------------------------------------------------------------------------------------------------------------
65
+ def __init__(self, name=None, is_daemon_thread=True, verbose_level=1):
66
+ #........................... | Instance Attributes | ...........................
67
+ type(self).__NEXT_ID += 1
68
+ if name is None:
69
+ self.name = str(type(self).__NEXT_ID)
70
+ else:
71
+ self.name = f"{name}{str(type(self).__NEXT_ID)}"
72
+ self.thread_id = None
73
+ self.verbose_level = verbose_level
74
+
75
+ #// Settings \\
76
+ self.is_daemon_thread = is_daemon_thread
77
+ self.join_timeout = 5 #secs
78
+
79
+ # // Control Variables \\
80
+ self.must_continue = False
81
+ self.has_finished = False
82
+ self.has_started = False
83
+
84
+ # // Agregated Objects \\
85
+ self.thread_handle = None
86
+ self.thread_args = None
87
+ self.on_after_finish_handler = None
88
+ self.run_once_func = None
89
+ #................................................................................
90
+ # ------------------------------------------------------------------------------------------------------------------
91
+ def sleep(self, interval_in_msecs):
92
+ time.sleep(interval_in_msecs / 1000.0)
93
+ # ------------------------------------------------------------------------------------------------------------------
94
+ def _thread_start(self, args):
95
+ self.thread_id = get_ident()
96
+ self.thread_args = args
97
+ self.has_started = True
98
+
99
+ if self.verbose_level > 0:
100
+ print(f"{self} is starting with arguments:", args)
101
+
102
+ self.has_finished = False
103
+ try:
104
+ if self.run_once_func is None:
105
+ self.loop()
106
+ else:
107
+ self.run_once_func(args)
108
+ finally:
109
+ self.has_finished = True
110
+ # ------------------------------------------------------------------------------------------------------------------
111
+ def _thread_finish(self):
112
+ while not self.has_finished:
113
+ pass
114
+
115
+ # Callback after finishing
116
+ if self.on_after_finish_handler is not None:
117
+ self.on_after_finish_handler()
118
+
119
+ # Signal the thread to stop via the event
120
+ self.thread_handle.stop()
121
+
122
+ # Wait for the thread to finish
123
+ if self.verbose_level > 1:
124
+ print(f"{self} joining...")
125
+
126
+ self.thread_handle.join(self.join_timeout)
127
+
128
+ if self.verbose_level > 1:
129
+ nTimeDelta = datetime.now() - self._stop_action_start
130
+ print(f"{self} joined after {(nTimeDelta.microseconds / 1000):.3f} msecs")
131
+ # ------------------------------------------------------------------------------------------------------------------
132
+ def start(self, args=None):
133
+ self.must_continue = True
134
+
135
+ self.thread_handle = ThreadEx(target=self._thread_start, args=(), kwargs={"args": args})
136
+ self.thread_handle.setDaemon(True)
137
+ self.thread_handle.start()
138
+ # ------------------------------------------------------------------------------------------------------------------
139
+ def resume(self, args=None):
140
+ if not self.has_started:
141
+ self.start(args)
142
+ # ------------------------------------------------------------------------------------------------------------------
143
+ def stop(self):
144
+ self._stop_action_start = datetime.now()
145
+ if self.verbose_level > 0:
146
+ print(f"{self} is stopping ...")
147
+ # Break the loop and wait for the method to exit
148
+ self.must_continue = False
149
+ self._thread_finish()
150
+ # ------------------------------------------------------------------------------------------------------------------
151
+ def terminate(self):
152
+ self.stop()
153
+ # ------------------------------------------------------------------------------------------------------------------
154
+ def loop(self):
155
+ pass
156
+ # ------------------------------------------------------------------------------------------------------------------
157
+ def __str__(self):
158
+ return f"{self.name} ({self.thread_id})"
159
+ # ------------------------------------------------------------------------------------------------------------------
160
+ def __repr__(self):
161
+ return self.__str__()
162
+ # ------------------------------------------------------------------------------------------------------------------
163
+ #=======================================================================================================================
164
+
165
+
166
+
167
+
168
+
169
+
170
+
171
+
172
+
173
+
174
+
175
+
@@ -0,0 +1,163 @@
1
+ # ======================================================================================
2
+ #
3
+ # Rapid Deep Neural Networks
4
+ #
5
+ # Licensed under the MIT License
6
+ # ______________________________________________________________________________________
7
+ # ......................................................................................
8
+
9
+ # Copyright (c) 2018-2025 Pantelis I. Kaplanoglou
10
+
11
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ # of this software and associated documentation files (the "Software"), to deal
13
+ # in the Software without restriction, including without limitation the rights
14
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ # copies of the Software, and to permit persons to whom the Software is
16
+ # furnished to do so, subject to the following conditions:
17
+
18
+ # The above copyright notice and this permission notice shall be included in all
19
+ # copies or substantial portions of the Software.
20
+
21
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ # SOFTWARE.
28
+
29
+ # .......................................................................................
30
+ from .semaphore_lock import SemaphoreLock
31
+
32
+
33
+
34
+ class ThreadSafeQueue(object):
35
+ #-------------------------------------------------------------------------------------------------------------------
36
+ def __init__(self, name="Queue", max_queued_items=None):
37
+ #........................... | Instance Attributes | ...........................
38
+ self.name = name
39
+ self.queue=[]
40
+
41
+ # // Settings \\
42
+ self.max_queued_items = max_queued_items
43
+ self.can_delete = True
44
+
45
+ # // Control Params \\
46
+ self.is_queue_locked = False
47
+
48
+ # // Composites \\
49
+ self.update_lock = SemaphoreLock()
50
+ #................................................................................
51
+
52
+ # -------------------------------------------------------------------------------------------------------------------
53
+ @property
54
+ def count(self):
55
+ return len(self.queue)
56
+
57
+ # -------------------------------------------------------------------------------------------------------------------
58
+ @property
59
+ def is_empty(self):
60
+ bResult = (len(self.queue) == 0)
61
+
62
+ return bResult
63
+ #-------------------------------------------------------------------------------------------------------------------
64
+ def push(self, value):
65
+ self.update_lock.lock()
66
+ try:
67
+ if self.max_queued_items is None:
68
+ bCanAppend = True
69
+ else:
70
+ bCanAppend = len(self.queue) < self.max_queued_items
71
+
72
+ if bCanAppend:
73
+ self.queue.append(value)
74
+ finally:
75
+ self.update_lock.unlock()
76
+ #-------------------------------------------------------------------------------------------------------------------
77
+ def pop(self, index=0):
78
+ nValue = None
79
+ if self.can_delete:
80
+ self.update_lock.lock()
81
+ try:
82
+ bMustPop = len(self.queue) > 0
83
+ if bMustPop:
84
+ if index == -1:
85
+ index = len(self.queue) - 1
86
+ nValue = self.queue.pop(index)
87
+ finally:
88
+ self.update_lock.unlock()
89
+
90
+ return nValue
91
+ #-------------------------------------------------------------------------------------------------------------------
92
+ def clear(self):
93
+ self.update_lock.lock()
94
+ try:
95
+ self.queue = []
96
+ finally:
97
+ self.update_lock.unlock()
98
+ #-------------------------------------------------------------------------------------------------------------------
99
+ '''
100
+ def pop_ex(self, index=0):
101
+ nValue,nRemainingItemCount = [None,None]
102
+ if self.can_delete:
103
+ self.update_lock.Lock()
104
+ try:
105
+ nRemainingItemCount = len(self.queue)
106
+ bMustPop = nRemainingItemCount > 0
107
+ if bMustPop:
108
+ if index == -1:
109
+ index = len(self.queue) - 1
110
+ nValue = self.queue.pop(index)
111
+ nRemainingItemCount = len(self.queue)
112
+ finally:
113
+ self.update_lock.UnLock()
114
+
115
+ return nValue, nRemainingItemCount
116
+ '''
117
+ #-------------------------------------------------------------------------------------------------------------------
118
+ def push_ex(self, message):
119
+ while self.is_queue_locked:
120
+ pass
121
+
122
+ if self.max_queued_items is None:
123
+ bCanAppend = True
124
+ else:
125
+ bCanAppend = len(self.queue) < self.max_queued_items
126
+
127
+ if not bCanAppend:
128
+ return
129
+
130
+ self.is_queue_locked = True
131
+ try:
132
+ self.queue.append(message)
133
+ finally:
134
+ self.is_queue_locked = False
135
+ #-------------------------------------------------------------------------------------------------------------------
136
+ def pop_ex(self):
137
+ sMessage = None
138
+ if self.can_delete:
139
+ while self.is_queue_locked:
140
+ pass
141
+
142
+ self.is_queue_locked = True
143
+ try:
144
+ if len(self.queue) > 0:
145
+ sMessage = self.queue.pop(0)
146
+ finally:
147
+ self.is_queue_locked = False
148
+
149
+ return sMessage
150
+ #-------------------------------------------------------------------------------------------------------------------
151
+
152
+
153
+
154
+
155
+
156
+
157
+
158
+
159
+
160
+
161
+
162
+
163
+
@@ -0,0 +1,66 @@
1
+ from .thread_safe_queue import ThreadSafeQueue
2
+
3
+ class StringCollectionThreadSafe(ThreadSafeQueue):
4
+ # -------------------------------------------------------------------------------------------------------------------
5
+ def __init__(self, filename=None, name="Text"):
6
+ super(StringCollectionThreadSafe, self).__init__(name)
7
+
8
+ self.filename = filename
9
+ self.__count = 0
10
+ self.__index = 0
11
+ # -------------------------------------------------------------------------------------------------------------------
12
+ def append(self, text):
13
+ self.push(text)
14
+ # -------------------------------------------------------------------------------------------------------------------
15
+ def print(self, text, *args):
16
+ if args is None:
17
+ self.push(text)
18
+ else:
19
+ self.push(text + " " + " ".join(map(str, args)))
20
+ # -------------------------------------------------------------------------------------------------------------------
21
+ def flush(self):
22
+ if self.CanDelete:
23
+ with open(self.filename, "a") as oFile:
24
+ for sLine in self.queue:
25
+ print(sLine, file=oFile)
26
+ self.clear()
27
+ # -------------------------------------------------------------------------------------------------------------------
28
+ def display_and_flush(self):
29
+ if self.CanDelete:
30
+ if self.filename is None:
31
+ for sLine in self.queue:
32
+ print(sLine)
33
+ else:
34
+ with open(self.filename, "a") as oFile:
35
+ for sLine in self.queue:
36
+ print(sLine, file=oFile)
37
+ self.clear()
38
+ # -------------------------------------------------------------------------------------------------------------------
39
+ def __iter__(self):
40
+ self.update_lock.Lock()
41
+ try:
42
+ self.__index = 0
43
+ self.__count = len(self.queue)
44
+ self.CanDelete = False
45
+ finally:
46
+ self.update_lock.UnLock()
47
+
48
+ return self
49
+ # -------------------------------------------------------------------------------------------------------------------
50
+ def __next__(self):
51
+ if self.__index < self.__count:
52
+ oResult = self.queue[self.__index]
53
+ self.__index += 1
54
+ return oResult
55
+ else:
56
+ self.CanDelete = True
57
+ raise StopIteration()
58
+ # -------------------------------------------------------------------------------------------------------------------
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+