TheSandmanAJM 0.1__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.
@@ -0,0 +1,17 @@
1
+ MIT License
2
+ Copyright (c) 2018 Andrew McSparron
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+ The above copyright notice and this permission notice shall be included in all
10
+ copies or substantial portions of the Software.
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17
+ SOFTWARE.
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: TheSandmanAJM
3
+ Version: 0.1
4
+ Summary: A utility class to facilitate and log time delays with custom sleep durations.
5
+ Home-page: https://github.com/amcsparron2793-Water/TheSandmanAJM
6
+ Download-URL: https://github.com/amcsparron2793-Water/TheSandmanAJM/archive/refs/tags/0.1.tar.gz
7
+ Author: Amcsparron
8
+ Author-email: amcsparron@albanyny.gov
9
+ License: MIT License
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Build Tools
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE.txt
17
+ Requires-Dist: tqdm
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: download-url
24
+ Dynamic: home-page
25
+ Dynamic: license
26
+ Dynamic: license-file
27
+ Dynamic: requires-dist
28
+ Dynamic: summary
29
+
30
+ # <u>TheSandmanAJM</u>
31
+ ### <i>A utility class to facilitate and log time delays with custom sleep durations.</i>
32
+
33
+
34
+ A utility class to facilitate and log time delays with custom sleep durations.
@@ -0,0 +1,5 @@
1
+ # <u>TheSandmanAJM</u>
2
+ ### <i>A utility class to facilitate and log time delays with custom sleep durations.</i>
3
+
4
+
5
+ A utility class to facilitate and log time delays with custom sleep durations.
@@ -0,0 +1,2 @@
1
+ from TheSandmanAJM.the_sandman import TheSandman
2
+ __all__ = ['TheSandman']
@@ -0,0 +1 @@
1
+ __version__ = '0.1'
@@ -0,0 +1,119 @@
1
+ from datetime import datetime
2
+ from logging import getLogger, Logger
3
+ from time import sleep
4
+
5
+ from tqdm import tqdm
6
+
7
+
8
+ class TheSandman:
9
+ """
10
+ A utility class to facilitate and log time delays with custom sleep durations.
11
+
12
+ Attributes:
13
+ DEFAULT_SLEEP_TIME_SECONDS (int): Default sleep duration in seconds if not specified.
14
+ sleep_time (int): Actual sleep time (in seconds) to be used by the instance.
15
+ sleep_time_string (str): Human-readable string representing the current sleep duration.
16
+ logger (Logger): Logging instance for logging messages related to sleep operations.
17
+
18
+ Methods:
19
+ sleep_time_string:
20
+ Property getter and setter for updating the human-readable sleep time string.
21
+
22
+ sleep_round():
23
+ Splits the sleep duration into two equal parts. It logs and prints messages depicting the current sleep state, including the remaining time, and sleeps for the given durations.
24
+ """
25
+ # default 600 secs = 10 minutes
26
+ DEFAULT_SLEEP_TIME_SECONDS = 600
27
+ DEFAULT_USE_VISUAL_SLEEP = True
28
+ DEFAULT_SILENT_SLEEP = False
29
+
30
+ def __init__(self, sleep_time_seconds=None, **kwargs):
31
+ self.sleep_time_start = None
32
+ self.use_visual_sleep = kwargs.get('use_visual_sleep', self.__class__.DEFAULT_USE_VISUAL_SLEEP)
33
+ self.silent_sleep = kwargs.get('silent_sleep', self.__class__.DEFAULT_SILENT_SLEEP)
34
+
35
+ self.sleep_time: int = sleep_time_seconds or self.__class__.DEFAULT_SLEEP_TIME_SECONDS
36
+ self._is_time_remaining = False
37
+ self._sleep_time_string = None
38
+
39
+ self.logger: Logger = kwargs.get('logger', getLogger(__name__))
40
+ self.sleep_time_string = self.sleep_time
41
+ self.logger.info(f'TheSandman initialized - sleep time set as {self.sleep_time_string}')
42
+
43
+ @property
44
+ def sleep_time_string(self):
45
+ return self._sleep_time_string
46
+
47
+ @sleep_time_string.setter
48
+ def sleep_time_string(self, value: int):
49
+ if self._is_time_remaining:
50
+ more = 'more'
51
+ else:
52
+ more = ''
53
+ if value >= 60:
54
+ self._sleep_time_string = f'sleeping for {value // 60} {more} minute(s)'
55
+ else:
56
+ self._sleep_time_string = f'sleeping for {value} {more} second(s)'
57
+
58
+ str_parts = [self._sleep_time_string, f'(started at {self.sleep_time_start})']
59
+ self._sleep_time_string = ' '.join(str_parts)
60
+
61
+ def _setup_sleep_in_rounds(self, **kwargs):
62
+ self.sleep_time_start = datetime.now().strftime('%m/%d/%Y %H:%M')
63
+ if self.use_visual_sleep:
64
+ kwargs['print_msg'] = False
65
+ elif self.silent_sleep:
66
+ kwargs['print_msg'] = False
67
+ else:
68
+ kwargs['print_msg'] = True
69
+ self._is_time_remaining = False
70
+ return kwargs
71
+
72
+ def _sleep_round(self, curr_sleep_round: int, total_rounds: int, print_msg: bool, **kwargs):
73
+ if curr_sleep_round == total_rounds - 1:
74
+ self._is_time_remaining = True
75
+ sleep_time_seconds = (self.sleep_time // total_rounds)
76
+ self.sleep(sleep_time_seconds, print_msg=print_msg, **kwargs)
77
+
78
+ def sleep_in_rounds(self, rounds=2, **kwargs):
79
+ kwargs = self._setup_sleep_in_rounds(**kwargs)
80
+
81
+ for sleep_round in range(rounds):
82
+ self._sleep_round(sleep_round, rounds, **kwargs)
83
+
84
+ def visual_sleep(self, sleep_time_seconds: int) -> None:
85
+ try:
86
+ for _ in tqdm(range(sleep_time_seconds),
87
+ desc=f"{self.sleep_time_string}",
88
+ unit="second"):
89
+ sleep(1)
90
+ except Exception as e:
91
+ if e.__class__.__name__ != 'KeyboardInterrupt':
92
+ self.logger.error(f"visual_sleep failed: {e}, turning off visual sleep and trying again...")
93
+ self.use_visual_sleep = False
94
+ self.sleep(sleep_time_seconds)
95
+ else:
96
+ raise
97
+
98
+ def sleep(self, sleep_time_seconds: int, **kwargs):
99
+ """
100
+ :param sleep_time_seconds: The number of seconds the function should pause execution.
101
+ :type sleep_time_seconds: int
102
+ :return: None
103
+ :rtype: None
104
+ """
105
+
106
+ self.sleep_time_string = self.sleep_time if not self._is_time_remaining else sleep_time_seconds
107
+ self.logger.info(self.sleep_time_string, **kwargs)
108
+
109
+ if self.use_visual_sleep:
110
+ self.visual_sleep(sleep_time_seconds)
111
+ else:
112
+ if not self.silent_sleep:
113
+ print(self.sleep_time_string)
114
+ sleep(sleep_time_seconds)
115
+
116
+
117
+ if __name__ == '__main__':
118
+ ts = TheSandman(sleep_time_seconds=30)
119
+ ts.sleep_in_rounds(rounds=3)
@@ -0,0 +1,34 @@
1
+ Metadata-Version: 2.4
2
+ Name: TheSandmanAJM
3
+ Version: 0.1
4
+ Summary: A utility class to facilitate and log time delays with custom sleep durations.
5
+ Home-page: https://github.com/amcsparron2793-Water/TheSandmanAJM
6
+ Download-URL: https://github.com/amcsparron2793-Water/TheSandmanAJM/archive/refs/tags/0.1.tar.gz
7
+ Author: Amcsparron
8
+ Author-email: amcsparron@albanyny.gov
9
+ License: MIT License
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Topic :: Software Development :: Build Tools
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Description-Content-Type: text/markdown
16
+ License-File: LICENSE.txt
17
+ Requires-Dist: tqdm
18
+ Dynamic: author
19
+ Dynamic: author-email
20
+ Dynamic: classifier
21
+ Dynamic: description
22
+ Dynamic: description-content-type
23
+ Dynamic: download-url
24
+ Dynamic: home-page
25
+ Dynamic: license
26
+ Dynamic: license-file
27
+ Dynamic: requires-dist
28
+ Dynamic: summary
29
+
30
+ # <u>TheSandmanAJM</u>
31
+ ### <i>A utility class to facilitate and log time delays with custom sleep durations.</i>
32
+
33
+
34
+ A utility class to facilitate and log time delays with custom sleep durations.
@@ -0,0 +1,14 @@
1
+ LICENSE.txt
2
+ README.md
3
+ pyproject.toml
4
+ setup.cfg
5
+ setup.py
6
+ TheSandmanAJM/__init__.py
7
+ TheSandmanAJM/_version.py
8
+ TheSandmanAJM/the_sandman.py
9
+ TheSandmanAJM.egg-info/PKG-INFO
10
+ TheSandmanAJM.egg-info/SOURCES.txt
11
+ TheSandmanAJM.egg-info/dependency_links.txt
12
+ TheSandmanAJM.egg-info/requires.txt
13
+ TheSandmanAJM.egg-info/top_level.txt
14
+ tests/test_the_sandman.py
@@ -0,0 +1 @@
1
+ TheSandmanAJM
@@ -0,0 +1,3 @@
1
+ [build-system]
2
+ requires = ["setuptools"]
3
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,7 @@
1
+ [metadata]
2
+ description_file = README.md
3
+
4
+ [egg_info]
5
+ tag_build =
6
+ tag_date = 0
7
+
@@ -0,0 +1,45 @@
1
+ from setuptools import setup
2
+ from pathlib import Path
3
+ import re
4
+
5
+ project_name = 'TheSandmanAJM'
6
+
7
+
8
+ def get_long_description():
9
+ this_dir = Path(__file__).parent
10
+ readme_path = this_dir / "README.md"
11
+ if readme_path.is_file():
12
+ long_description = (this_dir / "README.md").read_text()
13
+ else:
14
+ long_description = 'A utility class to facilitate and log time delays with custom sleep durations.'
15
+ return long_description
16
+
17
+
18
+ def get_property(prop, project):
19
+ result = re.search(r'{}\s*=\s*[\'"]([^\'"]*)[\'"]'.format(prop), open(project + '/_version.py').read())
20
+ return result.group(1)
21
+
22
+
23
+ setup(
24
+ name=project_name,
25
+ version=get_property('__version__', project_name),
26
+ packages=['TheSandmanAJM'],
27
+ url='https://github.com/amcsparron2793-Water/TheSandmanAJM',
28
+ download_url=f'https://github.com/amcsparron2793-Water/TheSandmanAJM/archive/refs/tags/{get_property("__version__", project_name)}.tar.gz',
29
+ keywords=[],
30
+ install_requires=['tqdm'],
31
+ license='MIT License',
32
+ author='Amcsparron',
33
+ author_email='amcsparron@albanyny.gov',
34
+ description='A utility class to facilitate and log time delays with custom sleep durations.',
35
+ long_description=get_long_description(),
36
+ long_description_content_type='text/markdown',
37
+ # this is for pypi categories etc
38
+ classifiers=[
39
+ 'Development Status :: 3 - Alpha', # Chose either "3 - Alpha", "4 - Beta" or "5 - Production/Stable" as the current state of your package
40
+ 'Intended Audience :: Developers', # Define that your audience are developers
41
+ 'Topic :: Software Development :: Build Tools',
42
+ 'License :: OSI Approved :: MIT License', # Again, pick a license
43
+ 'Programming Language :: Python :: 3', # Specify which python versions that you want to support
44
+ ]
45
+ )
@@ -0,0 +1,104 @@
1
+ import pytest
2
+ from unittest.mock import patch, MagicMock
3
+ from TheSandmanAJM.the_sandman import TheSandman
4
+
5
+
6
+ @pytest.fixture
7
+ def mock_logger():
8
+ return MagicMock()
9
+
10
+
11
+ @pytest.fixture
12
+ def sandman(mock_logger):
13
+ return TheSandman(sleep_time_seconds=10, logger=mock_logger)
14
+
15
+
16
+ def test_initialization_defaults():
17
+ ts = TheSandman()
18
+ assert ts.sleep_time == 600
19
+ assert ts.use_visual_sleep is True
20
+ assert ts.silent_sleep is False
21
+
22
+
23
+ def test_initialization_custom():
24
+ ts = TheSandman(sleep_time_seconds=30, use_visual_sleep=False, silent_sleep=True)
25
+ assert ts.sleep_time == 30
26
+ assert ts.use_visual_sleep is False
27
+ assert ts.silent_sleep is True
28
+
29
+
30
+ def test_sleep_time_string_seconds(sandman):
31
+ sandman.sleep_time_start = "2026-08-23 14:30"
32
+ sandman.sleep_time_string = 45
33
+ assert "sleeping for 45 second(s)" in sandman.sleep_time_string
34
+ assert "(started at 2026-08-23 14:30)" in sandman.sleep_time_string
35
+
36
+
37
+ def test_sleep_time_string_minutes(sandman):
38
+ sandman.sleep_time_start = "2026-08-23 14:30"
39
+ sandman.sleep_time_string = 125
40
+ assert "sleeping for 2 minute(s)" in sandman.sleep_time_string
41
+
42
+
43
+ def test_sleep_time_string_with_remaining(sandman):
44
+ sandman.sleep_time_start = "2026-08-23 14:30"
45
+ sandman._is_time_remaining = True
46
+ sandman.sleep_time_string = 30
47
+ assert "sleeping for 30 more second(s)" in sandman.sleep_time_string
48
+
49
+
50
+ def test_setup_sleep_in_rounds(sandman):
51
+ kwargs = sandman._setup_sleep_in_rounds(extra="data")
52
+ assert sandman.sleep_time_start is not None
53
+ assert sandman._is_time_remaining is False
54
+ assert kwargs['extra'] == "data"
55
+ # Since use_visual_sleep is True by default, print_msg should be False
56
+ assert kwargs['print_msg'] is False
57
+
58
+
59
+ @patch('TheSandmanAJM.the_sandman.sleep')
60
+ @patch('builtins.print')
61
+ def test_sleep_non_visual(mock_print, mock_sleep, sandman, mock_logger):
62
+ sandman.use_visual_sleep = False
63
+ sandman.silent_sleep = False
64
+ sandman.sleep(5)
65
+ mock_sleep.assert_called_once_with(5)
66
+ mock_print.assert_called_once()
67
+ mock_logger.info.assert_called()
68
+
69
+
70
+ @patch('TheSandmanAJM.the_sandman.TheSandman.visual_sleep')
71
+ def test_sleep_visual_calls_visual_sleep(mock_visual_sleep, sandman):
72
+ sandman.use_visual_sleep = True
73
+ sandman.sleep(5)
74
+ mock_visual_sleep.assert_called_once_with(5)
75
+
76
+
77
+ @patch('TheSandmanAJM.the_sandman.tqdm')
78
+ @patch('TheSandmanAJM.the_sandman.sleep')
79
+ def test_visual_sleep(mock_sleep, mock_tqdm, sandman):
80
+ # Mock tqdm to return a mock range
81
+ mock_tqdm.return_value = range(5)
82
+ sandman.visual_sleep(5)
83
+ assert mock_sleep.call_count == 5
84
+ mock_tqdm.assert_called_once()
85
+
86
+
87
+ @patch('TheSandmanAJM.the_sandman.TheSandman.sleep')
88
+ def test_sleep_in_rounds(mock_ts_sleep, sandman):
89
+ sandman.sleep_time = 30
90
+ sandman.sleep_in_rounds(rounds=3)
91
+ assert mock_ts_sleep.call_count == 3
92
+ # 30 // 3 = 10
93
+ mock_ts_sleep.assert_called_with(10, print_msg=False)
94
+
95
+
96
+ @patch('TheSandmanAJM.the_sandman.tqdm')
97
+ @patch('TheSandmanAJM.the_sandman.TheSandman.sleep')
98
+ def test_visual_sleep_exception_fallback(mock_ts_sleep, mock_tqdm, sandman, mock_logger):
99
+ mock_tqdm.side_effect = Exception("tqdm error")
100
+ sandman.use_visual_sleep = True
101
+ sandman.visual_sleep(5)
102
+ assert sandman.use_visual_sleep is False
103
+ mock_ts_sleep.assert_called_once_with(5)
104
+ mock_logger.error.assert_called()