sputchedtools 0.10.0__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,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: sputchedtools
3
+ Version: 0.10.0
4
+ Home-page: https://github.com/Sputchik/sputchedtools
5
+ Author: Sputchik
6
+ Author-email: sputchik@gmail.com
7
+ Requires-Python: >=3.8
8
+ Requires-Dist: aiohttp>=3.10.6
9
+ Requires-Dist: aiofiles>=24.1.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,17 @@
1
+ from setuptools import setup, find_packages
2
+
3
+ setup(
4
+ name = 'sputchedtools',
5
+ version = '0.10.0',
6
+ packages = find_packages(),
7
+ py_modules = ['sputchedtools'],
8
+ install_requires = [
9
+ 'aiohttp>=3.10.6',
10
+ 'aiofiles>=24.1.0',
11
+ # uvloop / winloop
12
+ ],
13
+ author = 'Sputchik',
14
+ author_email = 'sputchik@gmail.com',
15
+ url = 'https://github.com/Sputchik/sputchedtools',
16
+ python_requires = '>=3.8'
17
+ )
@@ -0,0 +1,9 @@
1
+ Metadata-Version: 2.1
2
+ Name: sputchedtools
3
+ Version: 0.10.0
4
+ Home-page: https://github.com/Sputchik/sputchedtools
5
+ Author: Sputchik
6
+ Author-email: sputchik@gmail.com
7
+ Requires-Python: >=3.8
8
+ Requires-Dist: aiohttp>=3.10.6
9
+ Requires-Dist: aiofiles>=24.1.0
@@ -0,0 +1,7 @@
1
+ setup.py
2
+ sputchedtools.py
3
+ sputchedtools.egg-info/PKG-INFO
4
+ sputchedtools.egg-info/SOURCES.txt
5
+ sputchedtools.egg-info/dependency_links.txt
6
+ sputchedtools.egg-info/requires.txt
7
+ sputchedtools.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ aiohttp>=3.10.6
2
+ aiofiles>=24.1.0
@@ -0,0 +1 @@
1
+ sputchedtools
@@ -0,0 +1,276 @@
1
+ class Timer:
2
+ """
3
+
4
+ Code execution Timer, use 'with' keyword
5
+
6
+ Accepts:
7
+ txt = '': text after main print message
8
+ decimals = 2: time difference precission
9
+
10
+ """
11
+
12
+ def __init__(self, txt = '', decimals = 2):
13
+ import time
14
+ self.time = time
15
+ self.txt = txt
16
+ self.decimals = decimals
17
+
18
+ def __enter__(self):
19
+ self.was = self.time.time()
20
+
21
+ def __exit__(self, f, u, c):
22
+ self.diff = format((self.time.time() - self.was), f'.{self.decimals}f')
23
+ print(f'\nTaken time: {self.diff}s {self.txt}')
24
+
25
+
26
+ class aio:
27
+ import asyncio, aiohttp, aiofiles
28
+
29
+ @staticmethod
30
+ async def request(
31
+ url: str,
32
+ toreturn: str = 'text',
33
+ session = None,
34
+ **kwargs,
35
+
36
+ ) -> tuple:
37
+
38
+ """
39
+ Accepts:
40
+ Args:
41
+ url
42
+ Kwargs:
43
+ toreturn: read, text, json
44
+ session: aiohttp.ClientSession
45
+ any other session.get() argument
46
+
47
+ Returns:
48
+ Valid response: (data, response.status)
49
+ status == 403: (-2, status)
50
+ status == 521: (-1, status)
51
+ status not in range(200, 400): (None, status)
52
+
53
+ Request Timeout: (0, None)
54
+ Cancelled Error: (None, None)
55
+ Exception: (-3, Exception as e)
56
+
57
+ """
58
+
59
+
60
+ created_session = False
61
+ if session is None:
62
+ session = aio.aiohttp.ClientSession()
63
+ created_session = True
64
+
65
+ try:
66
+ async with session.get(url, **kwargs) as response:
67
+
68
+ if 200 <= response.status < 300 and str(response.url)[-5:] != '/404/':
69
+ status = response.status
70
+
71
+ if toreturn == 'text':
72
+ data = await response.text()
73
+ elif toreturn == 'read':
74
+ data = await response.read()
75
+ elif toreturn == 'json':
76
+ data = await response.json()
77
+ else:
78
+ data = None
79
+
80
+ return data, status
81
+
82
+ elif status == 403:
83
+ # print('\nToo many requests...')
84
+ return -2, status
85
+
86
+ elif status == 521:
87
+ return -1, status
88
+
89
+ else: return None, status
90
+
91
+ except aio.asyncio.TimeoutError:
92
+ return 0, None
93
+
94
+ except aio.asyncio.CancelledError:
95
+ return None, None
96
+
97
+ except Exception as e:
98
+ # print(f'\nFailed to get response from {url}')
99
+ return -3, e
100
+
101
+ finally:
102
+ if created_session is True:
103
+ await session.close()
104
+
105
+ @staticmethod
106
+ async def post(url, session = None, toreturn = 'json', **kwargs):
107
+
108
+ created_session = False
109
+ if session is None:
110
+ session = aio.aiohttp.ClientSession()
111
+ created_session = True
112
+
113
+ try:
114
+
115
+ async with session.post(url, **kwargs) as response:
116
+ status = response.status
117
+
118
+ if 200 <= status < 300 and str(response.url)[-5:] != '/404/':
119
+
120
+ if toreturn == 'text':
121
+ data = await response.text()
122
+ elif toreturn == 'read':
123
+ data = await response.read()
124
+ elif toreturn == 'json':
125
+ data = await response.json()
126
+ else:
127
+ data = None
128
+
129
+ return data, status
130
+
131
+ else:
132
+ return None, status
133
+
134
+ except aio.asyncio.TimeoutError:
135
+ return 0, None
136
+
137
+ except aio.asyncio.CancelledError:
138
+ return None, None
139
+
140
+ except Exception as e:
141
+ # print(f'\nFailed to get response from {url}')
142
+ return -3, e
143
+
144
+ finally:
145
+ if created_session is True:
146
+ await session.close()
147
+
148
+ @staticmethod
149
+ async def open(file: str, action: str = 'read', mode: str = 'r', content = None, **kwargs):
150
+ async with aio.aiofiles.open(file, mode, **kwargs) as f:
151
+
152
+ if action == 'read': return await f.read()
153
+
154
+ elif action == 'write': return await f.write(content)
155
+
156
+ else: return None
157
+
158
+ @staticmethod
159
+ async def sem_task(
160
+ semaphore,
161
+ func: callable,
162
+ *args, **kwargs
163
+ ):
164
+
165
+ async with semaphore:
166
+ return await func(*args, **kwargs)
167
+
168
+ def enhance_loop():
169
+ import asyncio
170
+ from sys import platform
171
+
172
+ try:
173
+
174
+ if 'win' in platform:
175
+ import winloop # type: ignore
176
+ winloop.install()
177
+
178
+ else:
179
+ import uvloop # type: ignore
180
+ asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
181
+
182
+ return True
183
+
184
+ except ImportError:
185
+ return False
186
+
187
+ class num:
188
+
189
+ @staticmethod
190
+ def shorten(num: int | float, decimals = 2):
191
+
192
+ suffixes = ['k', 'm', 'b', 't']
193
+
194
+ if not isinstance(num, (int, float)):
195
+ return None
196
+
197
+ magnitude = 1000.0
198
+
199
+ sign = '-' if num < 0 else ''
200
+ num = abs(num)
201
+
202
+ if num < magnitude:
203
+ return f"{sign}{num}"
204
+
205
+ for i, suffix in enumerate(suffixes, start=1):
206
+ unit = magnitude ** i
207
+ if num < unit * magnitude:
208
+ num = format(num / unit, f'.{decimals}f')
209
+ return f"{sign}{num}{suffix}"
210
+
211
+ num = format(num / (magnitude ** len(suffixes)), f'.{decimals}f')
212
+ return f"{sign}{num}t"
213
+
214
+ @staticmethod
215
+ def unshorten(num: str) -> float | str:
216
+
217
+ multipliers = {'k': 10**3, 'm': 10**6, 'b': 10**9, 't': 10**12}
218
+
219
+ mp = num[-1].lower()
220
+ digit = num[:-1]
221
+
222
+ try:
223
+ digit = float(digit)
224
+ mp = multipliers[mp]
225
+ return digit * mp
226
+
227
+ except (ValueError, IndexError):
228
+ return num
229
+
230
+ @staticmethod
231
+ def decim_round(value: float, decimals: int = 2, precission: int = 20) -> str:
232
+ """
233
+
234
+ Accepts:
235
+ value: float - usually with mid-big decimals length
236
+ decimals: int - determines amount of digits (+2 for rounding, after decimal point) that will be used in 'calculations'
237
+ precission: int - determines precission level (format(value, f'.->{precission}<-f'
238
+
239
+ Returns:
240
+ accepted value:
241
+ if value == 0,
242
+ not isinstance(value & (decimals, precission), float & int)
243
+ decimals & value < 1
244
+
245
+ str-like float
246
+
247
+ """
248
+
249
+ if value == 0: return value
250
+ elif not isinstance(value, float): return value
251
+ elif not (decimals > 0 and isinstance(decimals, int)) or not (precission > 0 and isinstance(precission, int)): return value
252
+
253
+ str_val = format(value, f'.{precission}f')
254
+
255
+ integer = str_val.split('.')[0]
256
+ decim = str_val.split('.')[1]
257
+
258
+ if integer != '0':
259
+ i = 0
260
+
261
+ else:
262
+ for i in range(len(decim)):
263
+ if decim[i] != '0': break
264
+
265
+ decim = decim[i:i + decimals + 2].rstrip('0')
266
+
267
+ if decim == '':
268
+ return integer
269
+
270
+ if len(decim) > decimals:
271
+ rounded = str(round(float(decim[:-2] + '.' + decim[-2:]))).rstrip('0')
272
+ decim = '0' * i + rounded
273
+
274
+ else: decim = '0' * i + str(decim)
275
+
276
+ return integer + '.' + decim