tinytoolslib 0.5.0__tar.gz → 0.6.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.
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/PKG-INFO +3 -3
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/pyproject.toml +3 -3
- tinytoolslib-0.6.0/tinytoolslib/__version__.py +1 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/models.py +6 -30
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/requests.py +57 -5
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib.egg-info/PKG-INFO +3 -3
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib.egg-info/requires.txt +1 -1
- tinytoolslib-0.5.0/tinytoolslib/__version__.py +0 -1
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/README.md +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/setup.cfg +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/__init__.py +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/constants.py +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/discovery.py +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/exceptions.py +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/flash.py +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib/parsers.py +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib.egg-info/SOURCES.txt +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib.egg-info/dependency_links.txt +0 -0
- {tinytoolslib-0.5.0 → tinytoolslib-0.6.0}/tinytoolslib.egg-info/top_level.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tinytoolslib
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Set of tools for use with
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Set of tools for use with tinycontrol devices like LK2.X, LK3.X, LK4.X or tcPDU.
|
|
5
5
|
Author-email: Bartek Barszczewski <tinycontrol.software@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
7
|
Keywords: tinycontrol,lk,tcpdu
|
|
@@ -12,7 +12,7 @@ Description-Content-Type: text/markdown
|
|
|
12
12
|
Requires-Dist: aiohttp<4,>=3.9.3
|
|
13
13
|
Requires-Dist: netifaces<1,>=0.11.0
|
|
14
14
|
Requires-Dist: requests<3,>=2.31.0
|
|
15
|
-
Requires-Dist: tftpy
|
|
15
|
+
Requires-Dist: tftpy<=0.8.5,>=0.8.2
|
|
16
16
|
|
|
17
17
|
# tinyToolsLib
|
|
18
18
|
|
|
@@ -4,12 +4,12 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tinytoolslib"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.6.0"
|
|
8
8
|
authors = [
|
|
9
9
|
{ name="Bartek Barszczewski", email="tinycontrol.software@gmail.com" },
|
|
10
10
|
]
|
|
11
11
|
license = "Apache-2.0"
|
|
12
|
-
description = "Set of tools for use with
|
|
12
|
+
description = "Set of tools for use with tinycontrol devices like LK2.X, LK3.X, LK4.X or tcPDU."
|
|
13
13
|
requires-python = ">=3.7"
|
|
14
14
|
classifiers = [
|
|
15
15
|
"Programming Language :: Python :: 3",
|
|
@@ -19,7 +19,7 @@ dependencies = [
|
|
|
19
19
|
"aiohttp >= 3.9.3, < 4",
|
|
20
20
|
"netifaces >= 0.11.0, < 1",
|
|
21
21
|
"requests >= 2.31.0, < 3",
|
|
22
|
-
"tftpy >= 0.8.2,
|
|
22
|
+
"tftpy >= 0.8.2, <= 0.8.5",
|
|
23
23
|
]
|
|
24
24
|
readme = "README.md"
|
|
25
25
|
keywords = ["tinycontrol", "lk", "tcpdu"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = '0.6.0'
|
|
@@ -59,7 +59,6 @@ class DeviceModel(ABC):
|
|
|
59
59
|
session: Union[ClientSession, None] = None
|
|
60
60
|
|
|
61
61
|
_context: Dict[str, Dict] = field(init=False, default_factory=dict)
|
|
62
|
-
_close_session: bool = False
|
|
63
62
|
|
|
64
63
|
def __post_init__(self):
|
|
65
64
|
if self.schema == "https" and self.port != 443:
|
|
@@ -129,7 +128,9 @@ class DeviceModel(ABC):
|
|
|
129
128
|
password=self.password,
|
|
130
129
|
**kwargs,
|
|
131
130
|
)
|
|
132
|
-
|
|
131
|
+
parsed_data = response.get("parsed")
|
|
132
|
+
parsed_data["_ping"] = response.get("ping")
|
|
133
|
+
return self._get(parsed_data, path, skip_keys, remove_mapped_keys)
|
|
133
134
|
|
|
134
135
|
def set_out(self, index, value=None):
|
|
135
136
|
"""Set output state to value or toggle if value is None."""
|
|
@@ -215,9 +216,6 @@ class DeviceModel(ABC):
|
|
|
215
216
|
**kwargs,
|
|
216
217
|
):
|
|
217
218
|
"""Async version of get."""
|
|
218
|
-
if self.session is None:
|
|
219
|
-
self.session = ClientSession()
|
|
220
|
-
self._close_session = True
|
|
221
219
|
response = await async_get(
|
|
222
220
|
self.host,
|
|
223
221
|
path,
|
|
@@ -228,7 +226,9 @@ class DeviceModel(ABC):
|
|
|
228
226
|
session=self.session,
|
|
229
227
|
**kwargs,
|
|
230
228
|
)
|
|
231
|
-
|
|
229
|
+
parsed_data = response.get("parsed")
|
|
230
|
+
parsed_data["_ping"] = response.get("ping")
|
|
231
|
+
return self._get(parsed_data, path, skip_keys, remove_mapped_keys)
|
|
232
232
|
|
|
233
233
|
async def async_set_out(self, index, value=None):
|
|
234
234
|
"""Async set_out."""
|
|
@@ -265,30 +265,6 @@ class DeviceModel(ABC):
|
|
|
265
265
|
f"{self.__class__.__name__} does not support get_all command"
|
|
266
266
|
)
|
|
267
267
|
|
|
268
|
-
# region Session handling for asyncio
|
|
269
|
-
async def close(self) -> None:
|
|
270
|
-
"""Close open client session."""
|
|
271
|
-
await self.session.close()
|
|
272
|
-
|
|
273
|
-
async def __aenter__(self) -> "DeviceModel":
|
|
274
|
-
"""Async enter.
|
|
275
|
-
|
|
276
|
-
Returns
|
|
277
|
-
-------
|
|
278
|
-
The Device object.
|
|
279
|
-
"""
|
|
280
|
-
return self
|
|
281
|
-
|
|
282
|
-
async def __aexit__(self, *_exc_info: object) -> None:
|
|
283
|
-
"""Async exit.
|
|
284
|
-
|
|
285
|
-
Args:
|
|
286
|
-
----
|
|
287
|
-
_exc_info: Exec type.
|
|
288
|
-
"""
|
|
289
|
-
await self.close()
|
|
290
|
-
|
|
291
|
-
# endregion
|
|
292
268
|
# endregion
|
|
293
269
|
|
|
294
270
|
|
|
@@ -1,9 +1,21 @@
|
|
|
1
|
-
"""Functions to send HTTP requests via requests and aiohttp modules.
|
|
1
|
+
"""Functions to send HTTP requests via requests and aiohttp modules.
|
|
2
|
+
|
|
3
|
+
Ping can be included in response for aiohttp request if the ClientSession
|
|
4
|
+
uses our trace_configs. It can be achieved in two ways:
|
|
5
|
+
|
|
6
|
+
1. Using `get_session()` to get it with trace_configs set.
|
|
7
|
+
2. When creating own session adding `get_trace_config()` in constructor params:
|
|
8
|
+
```py
|
|
9
|
+
session = ClientSession(trace_configs=[get_trace_config()])
|
|
10
|
+
```
|
|
11
|
+
"""
|
|
2
12
|
|
|
3
13
|
import asyncio
|
|
4
14
|
import json
|
|
5
15
|
import socket
|
|
16
|
+
import time
|
|
6
17
|
from functools import wraps
|
|
18
|
+
from types import SimpleNamespace
|
|
7
19
|
from typing import Any, Dict, Union
|
|
8
20
|
from xml.etree import ElementTree
|
|
9
21
|
|
|
@@ -18,6 +30,7 @@ from aiohttp import (
|
|
|
18
30
|
ClientTimeout,
|
|
19
31
|
InvalidURL,
|
|
20
32
|
ServerDisconnectedError,
|
|
33
|
+
TraceConfig,
|
|
21
34
|
)
|
|
22
35
|
|
|
23
36
|
from .exceptions import (
|
|
@@ -35,6 +48,7 @@ DEFAULT_TIMEOUT = 3
|
|
|
35
48
|
DEFAULT_RETRIES = 1
|
|
36
49
|
|
|
37
50
|
|
|
51
|
+
# region Helper functions for handling requests/responses
|
|
38
52
|
def _parse_parameters(
|
|
39
53
|
host, path, schema, port, username, password, timeout, retries, verify
|
|
40
54
|
):
|
|
@@ -77,7 +91,7 @@ def _handle_errors(exc, response=None):
|
|
|
77
91
|
ClientConnectionError,
|
|
78
92
|
socket.gaierror,
|
|
79
93
|
) as exc:
|
|
80
|
-
raise TinyToolsRequestConnectionError("Connection error") from exc
|
|
94
|
+
raise TinyToolsRequestConnectionError(f"Connection error ({exc})") from exc
|
|
81
95
|
except (requests.exceptions.InvalidURL, InvalidURL) as exc:
|
|
82
96
|
raise TinyToolsRequestError("Invalid URL") from exc
|
|
83
97
|
except (requests.exceptions.HTTPError, ClientResponseError) as exc:
|
|
@@ -103,10 +117,12 @@ def _handle_content(content_type, content, response):
|
|
|
103
117
|
"_response": response,
|
|
104
118
|
"parsed": None,
|
|
105
119
|
}
|
|
106
|
-
# TODO: Add ping for requests method (ATM missing for aiohttp).
|
|
107
120
|
if hasattr(response, "elapsed"):
|
|
108
121
|
result["elapsed"] = response.elapsed.total_seconds()
|
|
109
|
-
result["ping"] = round(result["elapsed"] * 1000, 3)
|
|
122
|
+
result["ping"] = round(result["elapsed"] * 1000, 3) # in ms
|
|
123
|
+
elif hasattr(response, "elapsed_aio"):
|
|
124
|
+
result["elapsed"] = response.elapsed_aio
|
|
125
|
+
result["ping"] = round(result["elapsed"] * 1000, 3) # in ms
|
|
110
126
|
try:
|
|
111
127
|
if content_type == "application/json":
|
|
112
128
|
result["parsed"] = json.loads(content)
|
|
@@ -119,8 +135,10 @@ def _handle_content(content_type, content, response):
|
|
|
119
135
|
except (ElementTree.ParseError, ValueError) as exc:
|
|
120
136
|
raise TinyToolsRequestError("Cannot parse response") from exc
|
|
121
137
|
return result
|
|
138
|
+
# endregion
|
|
122
139
|
|
|
123
140
|
|
|
141
|
+
# region Synchronous requests
|
|
124
142
|
def request(
|
|
125
143
|
method: str,
|
|
126
144
|
host: str,
|
|
@@ -156,7 +174,7 @@ def request(
|
|
|
156
174
|
verify=verify,
|
|
157
175
|
)
|
|
158
176
|
response.raise_for_status()
|
|
159
|
-
except requests.exceptions.ConnectTimeout as exc:
|
|
177
|
+
except (requests.exceptions.ConnectTimeout, requests.exceptions.ReadTimeout) as exc:
|
|
160
178
|
if retries:
|
|
161
179
|
return request(
|
|
162
180
|
method,
|
|
@@ -209,6 +227,33 @@ def post(*args, **kwargs):
|
|
|
209
227
|
headers={"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"},
|
|
210
228
|
**kwargs,
|
|
211
229
|
)
|
|
230
|
+
# endregion
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
# region Asynchronous requests (aiohttp based)
|
|
234
|
+
async def on_request_start(session, trace_config_ctx, params):
|
|
235
|
+
"""Set timestamp for timing tracking."""
|
|
236
|
+
trace_config_ctx.start = time.perf_counter()
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
async def on_request_end(session, trace_config_ctx, params):
|
|
240
|
+
"""Calculate timing and set in the request context."""
|
|
241
|
+
elapsed = time.perf_counter() - trace_config_ctx.start
|
|
242
|
+
if hasattr(trace_config_ctx, "trace_request_ctx"):
|
|
243
|
+
trace_config_ctx.trace_request_ctx.elapsed = elapsed
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def get_trace_config() -> TraceConfig:
|
|
247
|
+
"""Return TraceConfig with signal handlers to track request timing."""
|
|
248
|
+
trace_config = TraceConfig()
|
|
249
|
+
trace_config.on_request_start.append(on_request_start)
|
|
250
|
+
trace_config.on_request_end.append(on_request_end)
|
|
251
|
+
return trace_config
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def get_session() -> ClientSession:
|
|
255
|
+
"""Return ClientSession with trace_config for timing tracking."""
|
|
256
|
+
return ClientSession(trace_configs=[get_trace_config()])
|
|
212
257
|
|
|
213
258
|
|
|
214
259
|
async def async_request(
|
|
@@ -238,6 +283,7 @@ async def async_request(
|
|
|
238
283
|
auth = BasicAuth(*auth)
|
|
239
284
|
response = None
|
|
240
285
|
try:
|
|
286
|
+
timing = SimpleNamespace(elapsed=None)
|
|
241
287
|
async with session.request(
|
|
242
288
|
method,
|
|
243
289
|
url,
|
|
@@ -245,9 +291,14 @@ async def async_request(
|
|
|
245
291
|
params=params,
|
|
246
292
|
timeout=ClientTimeout(total=timeout),
|
|
247
293
|
verify_ssl=verify,
|
|
294
|
+
trace_request_ctx=timing,
|
|
248
295
|
) as response:
|
|
249
296
|
response.raise_for_status()
|
|
250
297
|
content = await response.text()
|
|
298
|
+
# Try to handle timing
|
|
299
|
+
elapsed = timing.elapsed
|
|
300
|
+
if elapsed is not None:
|
|
301
|
+
response.elapsed_aio = elapsed
|
|
251
302
|
except (asyncio.TimeoutError, ClientOSError, ServerDisconnectedError) as exc:
|
|
252
303
|
# Retry only on timeout and few specific client connection errors
|
|
253
304
|
# (they happen randomly at least on Windows).
|
|
@@ -287,3 +338,4 @@ async def async_get(*args, silent=False, **kwargs):
|
|
|
287
338
|
if silent:
|
|
288
339
|
return None
|
|
289
340
|
raise
|
|
341
|
+
# endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tinytoolslib
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Set of tools for use with
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: Set of tools for use with tinycontrol devices like LK2.X, LK3.X, LK4.X or tcPDU.
|
|
5
5
|
Author-email: Bartek Barszczewski <tinycontrol.software@gmail.com>
|
|
6
6
|
License-Expression: Apache-2.0
|
|
7
7
|
Keywords: tinycontrol,lk,tcpdu
|
|
@@ -12,7 +12,7 @@ Description-Content-Type: text/markdown
|
|
|
12
12
|
Requires-Dist: aiohttp<4,>=3.9.3
|
|
13
13
|
Requires-Dist: netifaces<1,>=0.11.0
|
|
14
14
|
Requires-Dist: requests<3,>=2.31.0
|
|
15
|
-
Requires-Dist: tftpy
|
|
15
|
+
Requires-Dist: tftpy<=0.8.5,>=0.8.2
|
|
16
16
|
|
|
17
17
|
# tinyToolsLib
|
|
18
18
|
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = '0.5.0'
|
|
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
|