fb-tools 2.6.0__tar.gz → 2.6.2__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.
Files changed (65) hide show
  1. {fb_tools-2.6.0/lib/fb_tools.egg-info → fb_tools-2.6.2}/PKG-INFO +1 -1
  2. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/__init__.py +1 -1
  3. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/local_version.py +1 -1
  4. fb_tools-2.6.2/lib/fb_tools/spinner.py +587 -0
  5. {fb_tools-2.6.0 → fb_tools-2.6.2/lib/fb_tools.egg-info}/PKG-INFO +1 -1
  6. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools.egg-info/SOURCES.txt +3 -1
  7. fb_tools-2.6.2/test/test_50_spinner.py +126 -0
  8. {fb_tools-2.6.0 → fb_tools-2.6.2}/LICENSE +0 -0
  9. {fb_tools-2.6.0 → fb_tools-2.6.2}/MANIFEST.in +0 -0
  10. {fb_tools-2.6.0 → fb_tools-2.6.2}/README.md +0 -0
  11. {fb_tools-2.6.0 → fb_tools-2.6.2}/bin/get-file-to-remove +0 -0
  12. {fb_tools-2.6.0 → fb_tools-2.6.2}/bin/myip +0 -0
  13. {fb_tools-2.6.0 → fb_tools-2.6.2}/bin/update-ddns +0 -0
  14. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/app.py +0 -0
  15. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/argparse_actions.py +0 -0
  16. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/cfg_app.py +0 -0
  17. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/colcts.py +0 -0
  18. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/collections.py +0 -0
  19. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/common.py +0 -0
  20. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/config.py +0 -0
  21. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/ddns/__init__.py +0 -0
  22. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/ddns/config.py +0 -0
  23. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/ddns/errors.py +0 -0
  24. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/ddns/myip_app.py +0 -0
  25. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/ddns/update_app.py +0 -0
  26. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/errors.py +0 -0
  27. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/get_file_rm_app.py +0 -0
  28. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/handler/__init__.py +0 -0
  29. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/handler/lock.py +0 -0
  30. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/handling_obj.py +0 -0
  31. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/mailaddress.py +0 -0
  32. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/merge.py +0 -0
  33. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/multi_config/__init__.py +0 -0
  34. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/multi_config/files.py +0 -0
  35. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/multi_config/inits.py +0 -0
  36. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/multi_config/read.py +0 -0
  37. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/obj.py +0 -0
  38. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/pidfile.py +0 -0
  39. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools/xlate.py +0 -0
  40. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools.egg-info/dependency_links.txt +0 -0
  41. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools.egg-info/requires.txt +0 -0
  42. {fb_tools-2.6.0 → fb_tools-2.6.2}/lib/fb_tools.egg-info/top_level.txt +0 -0
  43. {fb_tools-2.6.0 → fb_tools-2.6.2}/locale/de/LC_MESSAGES/fb_tools.mo +0 -0
  44. {fb_tools-2.6.0 → fb_tools-2.6.2}/locale/de/LC_MESSAGES/fb_tools.po +0 -0
  45. {fb_tools-2.6.0 → fb_tools-2.6.2}/locale/en/LC_MESSAGES/fb_tools.mo +0 -0
  46. {fb_tools-2.6.0 → fb_tools-2.6.2}/locale/en/LC_MESSAGES/fb_tools.po +0 -0
  47. {fb_tools-2.6.0 → fb_tools-2.6.2}/locale/fb_tools.pot +0 -0
  48. {fb_tools-2.6.0 → fb_tools-2.6.2}/setup.cfg +0 -0
  49. {fb_tools-2.6.0 → fb_tools-2.6.2}/setup.py +0 -0
  50. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/call_script.sh +0 -0
  51. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/call_sleep.sh +0 -0
  52. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/do_sleep +0 -0
  53. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/general.py +0 -0
  54. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_00_errors.py +0 -0
  55. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_05_common.py +0 -0
  56. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_10_base_object.py +0 -0
  57. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_13_colcts.py +0 -0
  58. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_15_mailaddress.py +0 -0
  59. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_17_multicfg.py +0 -0
  60. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_18_pidfile.py +0 -0
  61. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_20_handling_object.py +0 -0
  62. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_25_ddns_update_status.py +0 -0
  63. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_30_base_handler.py +0 -0
  64. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_33_lock.py +0 -0
  65. {fb_tools-2.6.0 → fb_tools-2.6.2}/test/test_40_app_modules.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fb_tools
3
- Version: 2.6.0
3
+ Version: 2.6.2
4
4
  Summary: Modules for common used objects, error classes and methods.
5
5
  Home-page: https://github.com/fbrehm/python_fb_tools
6
6
  Author: Frank Brehm
@@ -22,6 +22,6 @@ DEFAULT_TERMINAL_HEIGHT = 40
22
22
  from .mailaddress import MailAddress, MailAddressList, QualifiedMailAddress # noqa: F401
23
23
  from .multi_config import BaseMultiConfig # noqa: F401
24
24
 
25
- __version__ = '2.6.0'
25
+ __version__ = '2.6.2'
26
26
 
27
27
  # vim: ts=4 et list
@@ -11,7 +11,7 @@
11
11
  __author__ = 'Frank Brehm <frank@brehm-online.com>'
12
12
  __copyright__ = '(C) 2024 by Frank Brehm, Berlin'
13
13
  __contact__ = 'frank@brehm-online.com'
14
- __version__ = '2.6.0'
14
+ __version__ = '2.6.2'
15
15
  __license__ = 'LGPL3+'
16
16
 
17
17
  # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
@@ -0,0 +1,587 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ @summary: Module for for a Spinner class.
5
+
6
+ A Spinner object is displaying on console a rotating or somehow
7
+ other animated character during its existence.
8
+
9
+ This class was taken from https://github.com/Tagar/stuff
10
+
11
+ Example usage:
12
+
13
+ from fb_tools.spinner import Spinner
14
+
15
+ with Spinner("just waiting a bit.. "):
16
+ time.sleep(3)
17
+
18
+ @author: Frank Brehm
19
+ @contact: frank@brehm-online.com
20
+ @copyright: © 2024 by Frank Brehm, Berlin
21
+ """
22
+
23
+ import itertools
24
+ import logging
25
+ import sys
26
+ import threading
27
+ import time
28
+ # from collections import namedtuple
29
+
30
+ # Own modules
31
+ # from .common import to_bytes
32
+ from .xlate import XLATOR
33
+
34
+ __version__ = '2.1.0'
35
+
36
+ _ = XLATOR.gettext
37
+
38
+ LOG = logging.getLogger(__name__)
39
+
40
+ CycleList = {
41
+ 'dots': {'delay': 80, 'frames': '⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏'},
42
+ 'dots2': {'delay': 80, 'frames': '⣾⣽⣻⢿⡿⣟⣯⣷'},
43
+ 'dots3': {'delay': 80, 'frames': '⠋⠙⠚⠞⠖⠦⠴⠲⠳⠓'},
44
+ 'dots4': {'delay': 80, 'frames': '⠄⠆⠇⠋⠙⠸⠰⠠⠰⠸⠙⠋⠇⠆'},
45
+ 'dots5': {'delay': 80, 'frames': '⠋⠙⠚⠒⠂⠂⠒⠲⠴⠦⠖⠒⠐⠐⠒⠓⠋'},
46
+ 'dots6': {'delay': 80, 'frames': '⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠴⠲⠒⠂⠂⠒⠚⠙⠉⠁'},
47
+ 'dots7': {'delay': 80, 'frames': '⠈⠉⠋⠓⠒⠐⠐⠒⠖⠦⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈'},
48
+ 'dots8': {'delay': 80, 'frames': '⠁⠁⠉⠙⠚⠒⠂⠂⠒⠲⠴⠤⠄⠄⠤⠠⠠⠤⠦⠖⠒⠐⠐⠒⠓⠋⠉⠈⠈'},
49
+ 'dots9': {'delay': 80, 'frames': '⢹⢺⢼⣸⣇⡧⡗⡏'},
50
+ 'dots10': {'delay': 80, 'frames': '⢄⢂⢁⡁⡈⡐⡠'},
51
+ 'dots11': {'delay': 100, 'frames': '⠁⠂⠄⡀⢀⠠⠐⠈'},
52
+ 'dots12': {
53
+ 'delay': 80,
54
+ 'frames': [
55
+ '⢀⠀',
56
+ '⡀⠀',
57
+ '⠄⠀',
58
+ '⢂⠀',
59
+ '⡂⠀',
60
+ '⠅⠀',
61
+ '⢃⠀',
62
+ '⡃⠀',
63
+ '⠍⠀',
64
+ '⢋⠀',
65
+ '⡋⠀',
66
+ '⠍⠁',
67
+ '⢋⠁',
68
+ '⡋⠁',
69
+ '⠍⠉',
70
+ '⠋⠉',
71
+ '⠋⠉',
72
+ '⠉⠙',
73
+ '⠉⠙',
74
+ '⠉⠩',
75
+ '⠈⢙',
76
+ '⠈⡙',
77
+ '⢈⠩',
78
+ '⡀⢙',
79
+ '⠄⡙',
80
+ '⢂⠩',
81
+ '⡂⢘',
82
+ '⠅⡘',
83
+ '⢃⠨',
84
+ '⡃⢐',
85
+ '⠍⡐',
86
+ '⢋⠠',
87
+ '⡋⢀',
88
+ '⠍⡁',
89
+ '⢋⠁',
90
+ '⡋⠁',
91
+ '⠍⠉',
92
+ '⠋⠉',
93
+ '⠋⠉',
94
+ '⠉⠙',
95
+ '⠉⠙',
96
+ '⠉⠩',
97
+ '⠈⢙',
98
+ '⠈⡙',
99
+ '⠈⠩',
100
+ '⠀⢙',
101
+ '⠀⡙',
102
+ '⠀⠩',
103
+ '⠀⢘',
104
+ '⠀⡘',
105
+ '⠀⠨',
106
+ '⠀⢐',
107
+ '⠀⡐',
108
+ '⠀⠠',
109
+ '⠀⢀',
110
+ '⠀⡀',
111
+ ],
112
+ },
113
+ 'dots8Bit': {
114
+ 'delay': 80,
115
+ 'frames': '⠀⠁⠂⠃⠄⠅⠆⠇⡀⡁⡂⡃⡄⡅⡆⡇⠈⠉⠊⠋⠌⠍⠎⠏⡈⡉⡊⡋⡌⡍⡎⡏⠐⠑⠒⠓⠔⠕⠖⠗⡐⡑⡒⡓⡔⡕⡖⡗⠘⠙⠚⠛⠜⠝⠞⠟⡘⡙'
116
+ '⡚⡛⡜⡝⡞⡟⠠⠡⠢⠣⠤⠥⠦⠧⡠⡡⡢⡣⡤⡥⡦⡧⠨⠩⠪⠫⠬⠭⠮⠯⡨⡩⡪⡫⡬⡭⡮⡯⠰⠱⠲⠳⠴⠵⠶⠷⡰⡱⡲⡳⡴⡵⡶⡷⠸⠹⠺⠻'
117
+ '⠼⠽⠾⠿⡸⡹⡺⡻⡼⡽⡾⡿⢀⢁⢂⢃⢄⢅⢆⢇⣀⣁⣂⣃⣄⣅⣆⣇⢈⢉⢊⢋⢌⢍⢎⢏⣈⣉⣊⣋⣌⣍⣎⣏⢐⢑⢒⢓⢔⢕⢖⢗⣐⣑⣒⣓⣔⣕'
118
+ '⣖⣗⢘⢙⢚⢛⢜⢝⢞⢟⣘⣙⣚⣛⣜⣝⣞⣟⢠⢡⢢⢣⢤⢥⢦⢧⣠⣡⣢⣣⣤⣥⣦⣧⢨⢩⢪⢫⢬⢭⢮⢯⣨⣩⣪⣫⣬⣭⣮⣯⢰⢱⢲⢳⢴⢵⢶⢷'
119
+ '⣰⣱⣲⣳⣴⣵⣶⣷⢸⢹⢺⢻⢼⢽⢾⢿⣸⣹⣺⣻⣼⣽⣾⣿',
120
+ },
121
+ 'line': {'delay': 130, 'frames': ['-', '\\', '|', '/']},
122
+ 'line1': {'delay': 100, 'frames': ['-', '/', '|', '\\']},
123
+ 'line2': {'delay': 100, 'frames': '⠂-–—–-'},
124
+ 'pipe': {'delay': 100, 'frames': '┤┘┴└├┌┬┐'},
125
+ 'simpleDots': {'delay': 400, 'frames': ['. ', '.. ', '...', ' ']},
126
+ 'simpleDotsScrolling': {'delay': 200, 'frames': ['. ', '.. ', '...', ' ..', ' .', ' ']},
127
+ 'star': {'delay': 70, 'frames': '✶✸✹✺✹✷'},
128
+ 'star2': {'delay': 80, 'frames': '+x*'},
129
+ 'flip': {'delay': 70, 'frames': "___-``'´-___"},
130
+ 'hamburger': {'delay': 100, 'frames': '☱☲☴'},
131
+ 'growVertical': {'delay': 120, 'frames': '▁▃▄▅▆▇▆▅▄▃'},
132
+ 'growHorizontal': {'delay': 120, 'frames': '▏▎▍▌▋▊▉▊▋▌▍▎'},
133
+ 'balloon': {'delay': 140, 'frames': ' .oO@* '},
134
+ 'balloon2': {'delay': 120, 'frames': '.oO°Oo.'},
135
+ 'noise': {'delay': 100, 'frames': '▓▒░'},
136
+ 'bounce': {'delay': 120, 'frames': '⠁⠂⠄⠂'},
137
+ 'boxBounce': {'delay': 120, 'frames': '▖▘▝▗'},
138
+ 'boxBounce2': {'delay': 100, 'frames': '▌▀▐▄'},
139
+ 'triangle': {'delay': 50, 'frames': '◢◣◤◥'},
140
+ 'arc': {'delay': 100, 'frames': '◜◠◝◞◡◟'},
141
+ 'circle': {'delay': 120, 'frames': '◡⊙◠'},
142
+ 'squareCorners': {'delay': 180, 'frames': '◰◳◲◱'},
143
+ 'circleQuarters': {'delay': 120, 'frames': '◴◷◶◵'},
144
+ 'circleHalves': {'delay': 50, 'frames': '◐◓◑◒'},
145
+ 'squish': {'delay': 100, 'frames': '╫╪'},
146
+ 'toggle': {'delay': 250, 'frames': '⊶⊷'},
147
+ 'toggle2': {'delay': 80, 'frames': '▫▪'},
148
+ 'toggle3': {'delay': 120, 'frames': '□■'},
149
+ 'toggle4': {'delay': 100, 'frames': '■□▪▫'},
150
+ 'toggle5': {'delay': 100, 'frames': '▮▯'},
151
+ 'toggle7': {'delay': 80, 'frames': '⦾⦿'},
152
+ 'toggle8': {'delay': 100, 'frames': '◍◌'},
153
+ 'toggle9': {'delay': 100, 'frames': '◉◎'},
154
+ 'toggle10': {'delay': 100, 'length': 2, 'frames': '㊂㊀㊁'},
155
+ 'toggle12': {'delay': 120, 'frames': '☗☖'},
156
+ 'toggle13': {'delay': 80, 'frames': '=*-'},
157
+ 'arrow': {'delay': 100, 'frames': '←↖↑↗→↘↓↙'},
158
+ 'arrow2': {
159
+ 'delay': 80,
160
+ 'length': 2,
161
+ 'frames': ['⬆️ ', '↗️ ', '➡️ ', '↘️ ', '⬇️ ', '↙️ ', '⬅️ ', '↖️ '],
162
+ },
163
+ 'arrow3': {
164
+ 'delay': 120,
165
+ 'frames': ['▹▹▹▹▹', '▸▹▹▹▹', '▹▸▹▹▹', '▹▹▸▹▹', '▹▹▹▸▹', '▹▹▹▹▸'],
166
+ },
167
+ 'bouncingBar': {
168
+ 'delay': 80,
169
+ 'frames': [
170
+ '[ ]',
171
+ '[= ]',
172
+ '[== ]',
173
+ '[=== ]',
174
+ '[ ===]',
175
+ '[ ==]',
176
+ '[ =]',
177
+ '[ ]',
178
+ '[ =]',
179
+ '[ ==]',
180
+ '[ ===]',
181
+ '[====]',
182
+ '[=== ]',
183
+ '[== ]',
184
+ '[= ]',
185
+ ],
186
+ },
187
+ 'bouncingBall': {
188
+ 'delay': 80,
189
+ 'frames': [
190
+ '( ● )',
191
+ '( ● )',
192
+ '( ● )',
193
+ '( ● )',
194
+ '( ●)',
195
+ '( ● )',
196
+ '( ● )',
197
+ '( ● )',
198
+ '( ● )',
199
+ '(● )',
200
+ ],
201
+ },
202
+ 'smiley': {'delay': 200, 'length': 2, 'frames': ['😄', '😝']},
203
+ 'monkey': {'delay': 300, 'length': 2, 'frames': ['🙈', '🙈', '🙉', '🙊']},
204
+ 'hearts': {'delay': 100, 'length': 2, 'frames': ['💛', '💙', '💜', '💚', '❤️ ']},
205
+ 'clock': {
206
+ 'delay': 100,
207
+ 'length': 2,
208
+ 'frames': [
209
+ '🕛',
210
+ '🕐',
211
+ '🕑',
212
+ '🕒',
213
+ '🕓',
214
+ '🕔',
215
+ '🕕',
216
+ '🕖',
217
+ '🕗',
218
+ '🕘',
219
+ '🕙',
220
+ '🕚',
221
+ ],
222
+ },
223
+ 'earth': {'delay': 180, 'length': 2, 'frames': ['🌍', '🌎', '🌏']},
224
+ 'material': {
225
+ 'delay': 17,
226
+ 'frames': [
227
+ '█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
228
+ '██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
229
+ '███▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
230
+ '████▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
231
+ '██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
232
+ '██████▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
233
+ '███████▁▁▁▁▁▁▁▁▁▁▁▁▁',
234
+ '████████▁▁▁▁▁▁▁▁▁▁▁▁',
235
+ '█████████▁▁▁▁▁▁▁▁▁▁▁',
236
+ '█████████▁▁▁▁▁▁▁▁▁▁▁',
237
+ '██████████▁▁▁▁▁▁▁▁▁▁',
238
+ '███████████▁▁▁▁▁▁▁▁▁',
239
+ '█████████████▁▁▁▁▁▁▁',
240
+ '██████████████▁▁▁▁▁▁',
241
+ '██████████████▁▁▁▁▁▁',
242
+ '▁██████████████▁▁▁▁▁',
243
+ '▁██████████████▁▁▁▁▁',
244
+ '▁██████████████▁▁▁▁▁',
245
+ '▁▁██████████████▁▁▁▁',
246
+ '▁▁▁██████████████▁▁▁',
247
+ '▁▁▁▁█████████████▁▁▁',
248
+ '▁▁▁▁██████████████▁▁',
249
+ '▁▁▁▁██████████████▁▁',
250
+ '▁▁▁▁▁██████████████▁',
251
+ '▁▁▁▁▁██████████████▁',
252
+ '▁▁▁▁▁██████████████▁',
253
+ '▁▁▁▁▁▁██████████████',
254
+ '▁▁▁▁▁▁██████████████',
255
+ '▁▁▁▁▁▁▁█████████████',
256
+ '▁▁▁▁▁▁▁█████████████',
257
+ '▁▁▁▁▁▁▁▁████████████',
258
+ '▁▁▁▁▁▁▁▁████████████',
259
+ '▁▁▁▁▁▁▁▁▁███████████',
260
+ '▁▁▁▁▁▁▁▁▁███████████',
261
+ '▁▁▁▁▁▁▁▁▁▁██████████',
262
+ '▁▁▁▁▁▁▁▁▁▁██████████',
263
+ '▁▁▁▁▁▁▁▁▁▁▁▁████████',
264
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁███████',
265
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁██████',
266
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████',
267
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████',
268
+ '█▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████',
269
+ '██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███',
270
+ '██▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███',
271
+ '███▁▁▁▁▁▁▁▁▁▁▁▁▁▁███',
272
+ '████▁▁▁▁▁▁▁▁▁▁▁▁▁▁██',
273
+ '█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█',
274
+ '█████▁▁▁▁▁▁▁▁▁▁▁▁▁▁█',
275
+ '██████▁▁▁▁▁▁▁▁▁▁▁▁▁█',
276
+ '████████▁▁▁▁▁▁▁▁▁▁▁▁',
277
+ '█████████▁▁▁▁▁▁▁▁▁▁▁',
278
+ '█████████▁▁▁▁▁▁▁▁▁▁▁',
279
+ '█████████▁▁▁▁▁▁▁▁▁▁▁',
280
+ '█████████▁▁▁▁▁▁▁▁▁▁▁',
281
+ '███████████▁▁▁▁▁▁▁▁▁',
282
+ '████████████▁▁▁▁▁▁▁▁',
283
+ '████████████▁▁▁▁▁▁▁▁',
284
+ '██████████████▁▁▁▁▁▁',
285
+ '██████████████▁▁▁▁▁▁',
286
+ '▁██████████████▁▁▁▁▁',
287
+ '▁██████████████▁▁▁▁▁',
288
+ '▁▁▁█████████████▁▁▁▁',
289
+ '▁▁▁▁▁████████████▁▁▁',
290
+ '▁▁▁▁▁████████████▁▁▁',
291
+ '▁▁▁▁▁▁███████████▁▁▁',
292
+ '▁▁▁▁▁▁▁▁█████████▁▁▁',
293
+ '▁▁▁▁▁▁▁▁█████████▁▁▁',
294
+ '▁▁▁▁▁▁▁▁▁█████████▁▁',
295
+ '▁▁▁▁▁▁▁▁▁█████████▁▁',
296
+ '▁▁▁▁▁▁▁▁▁▁█████████▁',
297
+ '▁▁▁▁▁▁▁▁▁▁▁████████▁',
298
+ '▁▁▁▁▁▁▁▁▁▁▁████████▁',
299
+ '▁▁▁▁▁▁▁▁▁▁▁▁███████▁',
300
+ '▁▁▁▁▁▁▁▁▁▁▁▁███████▁',
301
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁███████',
302
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁███████',
303
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█████',
304
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████',
305
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████',
306
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁████',
307
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███',
308
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁███',
309
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██',
310
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██',
311
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁██',
312
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█',
313
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█',
314
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁█',
315
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
316
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
317
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
318
+ '▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁',
319
+ ],
320
+ },
321
+ 'moon': {
322
+ 'delay': 80,
323
+ 'length': 2,
324
+ 'frames': ['🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘'],
325
+ },
326
+ 'runner': {'delay': 140, 'length': 2, 'frames': ['🚶', '🏃']},
327
+ 'pong': {
328
+ 'delay': 80,
329
+ 'frames': [
330
+ '▐⠂ ▌',
331
+ '▐⠈ ▌',
332
+ '▐ ⠂ ▌',
333
+ '▐ ⠠ ▌',
334
+ '▐ ⡀ ▌',
335
+ '▐ ⠠ ▌',
336
+ '▐ ⠂ ▌',
337
+ '▐ ⠈ ▌',
338
+ '▐ ⠂ ▌',
339
+ '▐ ⠠ ▌',
340
+ '▐ ⡀ ▌',
341
+ '▐ ⠠ ▌',
342
+ '▐ ⠂ ▌',
343
+ '▐ ⠈ ▌',
344
+ '▐ ⠂▌',
345
+ '▐ ⠠▌',
346
+ '▐ ⡀▌',
347
+ '▐ ⠠ ▌',
348
+ '▐ ⠂ ▌',
349
+ '▐ ⠈ ▌',
350
+ '▐ ⠂ ▌',
351
+ '▐ ⠠ ▌',
352
+ '▐ ⡀ ▌',
353
+ '▐ ⠠ ▌',
354
+ '▐ ⠂ ▌',
355
+ '▐ ⠈ ▌',
356
+ '▐ ⠂ ▌',
357
+ '▐ ⠠ ▌',
358
+ '▐ ⡀ ▌',
359
+ '▐⠠ ▌',
360
+ ],
361
+ },
362
+ 'shark': {
363
+ 'delay': 120,
364
+ 'frames': [
365
+ '▐|\\____________▌',
366
+ '▐_|\\___________▌',
367
+ '▐__|\\__________▌',
368
+ '▐___|\\_________▌',
369
+ '▐____|\\________▌',
370
+ '▐_____|\\_______▌',
371
+ '▐______|\\______▌',
372
+ '▐_______|\\_____▌',
373
+ '▐________|\\____▌',
374
+ '▐_________|\\___▌',
375
+ '▐__________|\\__▌',
376
+ '▐___________|\\_▌',
377
+ '▐____________|\\▌',
378
+ '▐____________/|▌',
379
+ '▐___________/|_▌',
380
+ '▐__________/|__▌',
381
+ '▐_________/|___▌',
382
+ '▐________/|____▌',
383
+ '▐_______/|_____▌',
384
+ '▐______/|______▌',
385
+ '▐_____/|_______▌',
386
+ '▐____/|________▌',
387
+ '▐___/|_________▌',
388
+ '▐__/|__________▌',
389
+ '▐_/|___________▌',
390
+ '▐/|____________▌',
391
+ ],
392
+ },
393
+ 'dqpb': {'delay': 100, 'frames': 'dqpb'},
394
+ 'weather': {
395
+ 'delay': 100,
396
+ 'length': 2,
397
+ 'frames': [
398
+ '☀️ ',
399
+ '☀️ ',
400
+ '☀️ ',
401
+ '🌤 ',
402
+ '⛅️',
403
+ '🌥 ',
404
+ '☁️ ',
405
+ '🌧 ',
406
+ '🌨 ',
407
+ '🌧 ',
408
+ '🌨 ',
409
+ '🌧 ',
410
+ '🌨 ',
411
+ '⛈ ',
412
+ '🌨 ',
413
+ '🌧 ',
414
+ '🌨 ',
415
+ '☁️ ',
416
+ '🌥 ',
417
+ '⛅️',
418
+ '🌤 ',
419
+ '☀️ ',
420
+ '☀️ ',
421
+ ],
422
+ },
423
+ 'christmas': {'delay': 400, 'length': 2, 'frames': '🌲🎄'},
424
+ 'grenade': {
425
+ 'delay': 80,
426
+ 'length': 3,
427
+ 'frames': [
428
+ '، ',
429
+ '′ ',
430
+ ' ´ ',
431
+ ' ‾ ',
432
+ ' ⸌',
433
+ ' ⸊',
434
+ ' |',
435
+ ' ⁎',
436
+ ' ⁕',
437
+ ' ෴ ',
438
+ ' ⁓',
439
+ ' ',
440
+ ' ',
441
+ ' ',
442
+ ],
443
+ },
444
+ 'point': {'delay': 125, 'frames': ['∙∙∙', '●∙∙', '∙●∙', '∙∙●', '∙∙∙']},
445
+ 'layer': {'delay': 150, 'frames': '-=≡'},
446
+ 'betaWave': {
447
+ 'delay': 80,
448
+ 'frames': [
449
+ 'ρββββββ',
450
+ 'βρβββββ',
451
+ 'ββρββββ',
452
+ 'βββρβββ',
453
+ 'ββββρββ',
454
+ 'βββββρβ',
455
+ 'ββββββρ',
456
+ ],
457
+ },
458
+ 'aesthetic': {
459
+ 'delay': 80,
460
+ 'frames': [
461
+ '▰▱▱▱▱▱▱',
462
+ '▰▰▱▱▱▱▱',
463
+ '▰▰▰▱▱▱▱',
464
+ '▰▰▰▰▱▱▱',
465
+ '▰▰▰▰▰▱▱',
466
+ '▰▰▰▰▰▰▱',
467
+ '▰▰▰▰▰▰▰',
468
+ '▰▱▱▱▱▱▱',
469
+ ],
470
+ },
471
+ }
472
+
473
+ # =============================================================================
474
+ class Spinner(object):
475
+ """Displaying on console a rotating or somehow other animated character."""
476
+
477
+ default_cycle_name = 'line1'
478
+ default_delay = 100
479
+
480
+ # -------------------------------------------------------------------------
481
+ def __init__(self, message, cycle_name=None, frames=None, delay=None):
482
+ """Initialize a Spinner object."""
483
+ self.cycle_name = cycle_name
484
+ if not self.cycle_name:
485
+ self.cycle_name = self.default_cycle_name
486
+
487
+ self.frames = None
488
+ self.delay = self.default_delay
489
+ self.characters = 1
490
+ length = None
491
+
492
+ if frames:
493
+ self.frames = frames
494
+ else:
495
+ if self.cycle_name not in CycleList:
496
+ msg = _('Spinner {!r} not found.').format(self.cycle_name)
497
+ raise KeyError(msg)
498
+
499
+ self.frames = CycleList[self.cycle_name]['frames']
500
+ self.delay = CycleList[self.cycle_name]['delay']
501
+ if 'length' in CycleList[self.cycle_name]:
502
+ length = CycleList[self.cycle_name]['length']
503
+
504
+ self.spinner = itertools.cycle(self.frames)
505
+
506
+ if length:
507
+ self.characters = length
508
+ else:
509
+ self.characters = len(self.frames[0])
510
+ if delay:
511
+ self.delay = delay
512
+
513
+ # LOG.debug('First frame is of type {!r}.'.format(self.frames[0].__class__.__name__))
514
+ # LOG.debug('Frames has {c} characters, delay is {d} milliseconds.'.format(
515
+ # c=self.characters, d=self.delay))
516
+ # len_in_codeunits = len(self.frames[0].encode('utf-16-le')) // 2
517
+ # LOG.debug('len_in_codeunits: {}'.format(len_in_codeunits))
518
+ # LOG.debug('len: {}'.format(len(self.frames[0].encode('utf-8'))))
519
+ # LOG.debug('str: {}'.format(self.frames[0]))
520
+ # LOG.debug('bytes: {}'.format(to_bytes(self.frames[0])))
521
+
522
+ self.busy = False
523
+ self.spinner_visible = False
524
+ sys.stdout.write(message)
525
+
526
+ # -------------------------------------------------------------------------
527
+ def write_next(self):
528
+ """Write the next character from the cycle array on the current screen position."""
529
+ with self._screen_lock:
530
+ if not self.spinner_visible:
531
+ sys.stdout.write(next(self.spinner) + ' ')
532
+ self.spinner_visible = True
533
+ sys.stdout.flush()
534
+
535
+ # -------------------------------------------------------------------------
536
+ def remove_spinner(self, cleanup=False):
537
+ """
538
+ Remove the last visible cycle character from screen.
539
+
540
+ If the parameter cleanup is true, then the screen cursor will be mnoved to the next line.
541
+ """
542
+ with self._screen_lock:
543
+ if self.spinner_visible:
544
+ sys.stdout.write('\b' * (self.characters + 1))
545
+ self.spinner_visible = False
546
+ if cleanup:
547
+ sys.stdout.write(' ' * self.characters) # overwrite spinner with blank
548
+ sys.stdout.write('\r') # move to next line
549
+ sys.stdout.flush()
550
+
551
+ # -------------------------------------------------------------------------
552
+ def spinner_task(self):
553
+ """Entry point of the Thread. It is an infinite loop."""
554
+ delay = float(self.delay) / 1000.0
555
+
556
+ while self.busy:
557
+ self.write_next()
558
+ time.sleep(delay)
559
+ self.remove_spinner()
560
+
561
+ # -------------------------------------------------------------------------
562
+ def __enter__(self):
563
+ """Execute this ction, when this object will be created for the with-block."""
564
+ if sys.stdout.isatty():
565
+ self._screen_lock = threading.Lock()
566
+ self.busy = True
567
+ self.thread = threading.Thread(target=self.spinner_task)
568
+ self.thread.start()
569
+
570
+ # -------------------------------------------------------------------------
571
+ def __exit__(self, exc_type, exc_val, exc_traceback):
572
+ """Exit action at the end of the with-block."""
573
+ if sys.stdout.isatty():
574
+ self.busy = False
575
+ self.remove_spinner(cleanup=True)
576
+ else:
577
+ sys.stdout.write('\r')
578
+
579
+
580
+ # =============================================================================
581
+ if __name__ == '__main__':
582
+
583
+ pass
584
+
585
+ # =============================================================================
586
+
587
+ # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fb_tools
3
- Version: 2.6.0
3
+ Version: 2.6.2
4
4
  Summary: Modules for common used objects, error classes and methods.
5
5
  Home-page: https://github.com/fbrehm/python_fb_tools
6
6
  Author: Frank Brehm
@@ -22,6 +22,7 @@ lib/fb_tools/mailaddress.py
22
22
  lib/fb_tools/merge.py
23
23
  lib/fb_tools/obj.py
24
24
  lib/fb_tools/pidfile.py
25
+ lib/fb_tools/spinner.py
25
26
  lib/fb_tools/xlate.py
26
27
  lib/fb_tools.egg-info/PKG-INFO
27
28
  lib/fb_tools.egg-info/SOURCES.txt
@@ -59,4 +60,5 @@ test/test_20_handling_object.py
59
60
  test/test_25_ddns_update_status.py
60
61
  test/test_30_base_handler.py
61
62
  test/test_33_lock.py
62
- test/test_40_app_modules.py
63
+ test/test_40_app_modules.py
64
+ test/test_50_spinner.py
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ @summary: Test script (and module) for unit tests on spinner module and Spinner objects.
5
+
6
+ @author: Frank Brehm
7
+ @contact: frank@brehm-online.com
8
+ @license: GPL3
9
+ """
10
+
11
+ import logging
12
+ import os
13
+ import sys
14
+ import time
15
+
16
+ try:
17
+ import unittest2 as unittest
18
+ except ImportError:
19
+ import unittest
20
+
21
+ libdir = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]), '..', 'lib'))
22
+ sys.path.insert(0, libdir)
23
+
24
+ from fb_tools.common import to_bool
25
+
26
+ from general import FbToolsTestcase, get_arg_verbose, init_root_logger
27
+
28
+
29
+ APPNAME = 'test_spinner'
30
+
31
+ LOG = logging.getLogger(APPNAME)
32
+
33
+ EXEC_LONG_TESTS = False
34
+ if 'EXEC_LONG_TESTS' in os.environ and os.environ['EXEC_LONG_TESTS'] != '':
35
+ EXEC_LONG_TESTS = to_bool(os.environ['EXEC_LONG_TESTS'])
36
+
37
+ SPINNER_TO_TEST = 'line'
38
+ if 'SPINNER_TO_TEST' in os.environ:
39
+ SPINNER_TO_TEST = os.environ['SPINNER_TO_TEST'].strip()
40
+ if not SPINNER_TO_TEST:
41
+ SPINNER_TO_TEST = None
42
+
43
+ # =============================================================================
44
+ class TestSpinner(FbToolsTestcase):
45
+ """Testcase for unit tests on module fb_tools.spinner."""
46
+
47
+ # -------------------------------------------------------------------------
48
+ def setUp(self):
49
+ """Execute this on setting up before calling each particular test method."""
50
+ if self.verbose >= 1:
51
+ print()
52
+
53
+ # -------------------------------------------------------------------------
54
+ def tearDown(self):
55
+ """Tear down routine for calling each particular test method."""
56
+ pass
57
+
58
+ # -------------------------------------------------------------------------
59
+ def test_import(self):
60
+ """Test import of pp_admintools.spinner."""
61
+ LOG.info(self.get_method_doc())
62
+
63
+ import fb_tools.spinner
64
+ LOG.debug('Version of module fb_tools.spinner: {!r}.'.format(
65
+ fb_tools.spinner.__version__))
66
+
67
+ # -------------------------------------------------------------------------
68
+ @unittest.skipUnless(SPINNER_TO_TEST, 'No spinner to test selected.')
69
+ def test_particular_spinner(self):
70
+ """Test execution of a particular spinner."""
71
+ LOG.info(self.get_method_doc())
72
+
73
+ from fb_tools.spinner import Spinner
74
+
75
+ seconds_per_spinner = 10
76
+
77
+ msg = 'Testing spinner {!r}: '.format(SPINNER_TO_TEST)
78
+ with Spinner(msg, SPINNER_TO_TEST):
79
+ time.sleep(seconds_per_spinner)
80
+ print()
81
+ print('Continue ...')
82
+
83
+ # -------------------------------------------------------------------------
84
+ @unittest.skipUnless(EXEC_LONG_TESTS, 'Long terming tests are not executed.')
85
+ def test_all_spinners(self):
86
+ """Test execution of all spinners."""
87
+ LOG.info(self.get_method_doc())
88
+
89
+ import fb_tools.spinner
90
+ from fb_tools.spinner import Spinner
91
+
92
+ seconds_per_spinner = 6
93
+
94
+ for cycle_name in fb_tools.spinner.CycleList.keys():
95
+
96
+ msg = 'Testing spinner {!r}: '.format(cycle_name)
97
+ with Spinner(msg, cycle_name):
98
+ time.sleep(seconds_per_spinner)
99
+ print()
100
+
101
+
102
+ # =============================================================================
103
+ if __name__ == '__main__':
104
+
105
+ verbose = get_arg_verbose()
106
+ if verbose is None:
107
+ verbose = 0
108
+ init_root_logger(verbose)
109
+
110
+ LOG.info('Starting tests ...')
111
+
112
+ loader = unittest.TestLoader()
113
+ suite = unittest.TestSuite()
114
+
115
+ suite.addTest(TestSpinner('test_import', verbose))
116
+ suite.addTest(TestSpinner('test_particular_spinner', verbose))
117
+ suite.addTest(TestSpinner('test_all_spinners', verbose))
118
+
119
+ runner = unittest.TextTestRunner(verbosity=verbose)
120
+
121
+ result = runner.run(suite)
122
+
123
+
124
+ # =============================================================================
125
+
126
+ # vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes