libentry 1.21.3__py3-none-any.whl → 1.22__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.
- libentry/api.py +32 -11
- libentry/json.py +52 -24
- libentry/utils.py +34 -0
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/METADATA +1 -1
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/RECORD +10 -9
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/LICENSE +0 -0
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/WHEEL +0 -0
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/entry_points.txt +0 -0
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/top_level.txt +0 -0
- {libentry-1.21.3.dist-info → libentry-1.22.dist-info}/zip-safe +0 -0
libentry/api.py
CHANGED
@@ -14,7 +14,7 @@ import asyncio
|
|
14
14
|
from dataclasses import dataclass, field
|
15
15
|
from time import sleep
|
16
16
|
from typing import Any, AsyncIterable, Callable, Iterable, List, Literal, Mapping, Optional, Tuple, Union
|
17
|
-
from urllib.parse import urljoin
|
17
|
+
from urllib.parse import urlencode, urljoin
|
18
18
|
|
19
19
|
import httpx
|
20
20
|
from urllib3 import PoolManager
|
@@ -217,10 +217,7 @@ class BaseClient:
|
|
217
217
|
stream: bool,
|
218
218
|
verify: bool,
|
219
219
|
) -> Union[bytes, Iterable[bytes]]:
|
220
|
-
if headers is None
|
221
|
-
headers = self.headers
|
222
|
-
else:
|
223
|
-
headers = {**self.headers, **headers}
|
220
|
+
headers = self.headers if headers is None else {**self.headers, **headers}
|
224
221
|
response = self.URLLIB3_POOL[int(verify)].request(
|
225
222
|
method=method,
|
226
223
|
url=url,
|
@@ -309,10 +306,7 @@ class BaseClient:
|
|
309
306
|
stream: bool,
|
310
307
|
verify: bool,
|
311
308
|
):
|
312
|
-
if headers is None
|
313
|
-
headers = self.headers
|
314
|
-
else:
|
315
|
-
headers = {**self.headers, **headers}
|
309
|
+
headers = self.headers if headers is None else {**self.headers, **headers}
|
316
310
|
if not stream:
|
317
311
|
async with httpx.AsyncClient(headers=headers, verify=verify) as client:
|
318
312
|
response = await client.request(
|
@@ -392,6 +386,19 @@ class BaseClient:
|
|
392
386
|
|
393
387
|
class APIClient(BaseClient):
|
394
388
|
|
389
|
+
@staticmethod
|
390
|
+
def _encode_params(data):
|
391
|
+
result = []
|
392
|
+
for k, v in data.items():
|
393
|
+
if v is not None:
|
394
|
+
result.append(
|
395
|
+
(
|
396
|
+
k.encode("utf-8") if isinstance(k, str) else k,
|
397
|
+
v.encode("utf-8") if isinstance(v, str) else v,
|
398
|
+
)
|
399
|
+
)
|
400
|
+
return urlencode(result, doseq=True)
|
401
|
+
|
395
402
|
def request(
|
396
403
|
self,
|
397
404
|
method: Literal["GET", "POST"],
|
@@ -417,7 +424,14 @@ class APIClient(BaseClient):
|
|
417
424
|
headers = {}
|
418
425
|
accept = headers["Accept"] if "Accept" in headers else self.headers["Accept"]
|
419
426
|
headers["Accept"] = accept + f"; stream={int(stream)}"
|
420
|
-
|
427
|
+
content_type = headers.get("Content-Type")
|
428
|
+
if content_type is None or content_type == "application/json":
|
429
|
+
body = json.dumps(json_data) if json_data is not None else None
|
430
|
+
elif content_type == "application/x-www-form-urlencoded":
|
431
|
+
body = self._encode_params(json_data)
|
432
|
+
else:
|
433
|
+
raise ValueError(f"Unsupported content type \"{content_type}\".")
|
434
|
+
|
421
435
|
content = super().request(
|
422
436
|
method,
|
423
437
|
full_url,
|
@@ -571,7 +585,14 @@ class APIClient(BaseClient):
|
|
571
585
|
headers = {}
|
572
586
|
accept = headers["Accept"] if "Accept" in headers else self.headers["Accept"]
|
573
587
|
headers["Accept"] = accept + f"; stream={int(stream)}"
|
574
|
-
|
588
|
+
content_type = headers.get("Content-Type")
|
589
|
+
if content_type is None or content_type == "application/json":
|
590
|
+
body = json.dumps(json_data) if json_data is not None else None
|
591
|
+
elif content_type == "application/x-www-form-urlencoded":
|
592
|
+
body = self._encode_params(json_data)
|
593
|
+
else:
|
594
|
+
raise ValueError(f"Unsupported content type \"{content_type}\".")
|
595
|
+
|
575
596
|
content = await super().request_async(
|
576
597
|
method,
|
577
598
|
full_url,
|
libentry/json.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
#!/usr/bin/env python3
|
2
2
|
|
3
|
+
__author__ = "xi"
|
3
4
|
__all__ = [
|
4
5
|
"dump",
|
5
6
|
"dumps",
|
@@ -13,41 +14,35 @@ from functools import partial
|
|
13
14
|
|
14
15
|
import numpy as np
|
15
16
|
|
17
|
+
_BINDINGS = []
|
16
18
|
|
17
|
-
def encode_ndarray(a: np.ndarray):
|
18
|
-
shape = a.shape
|
19
|
-
dtype = a.dtype
|
20
|
-
data = a.tobytes(order="C")
|
21
|
-
data = b64encode(data).decode()
|
22
|
-
return {
|
23
|
-
"__TYPE__": "numpy",
|
24
|
-
"shape": shape,
|
25
|
-
"dtype": str(dtype),
|
26
|
-
"data": data
|
27
|
-
}
|
28
19
|
|
20
|
+
def bind(name, type_):
|
21
|
+
def _wrapper(cls):
|
22
|
+
_BINDINGS.append((name, type_, cls()))
|
23
|
+
return cls
|
29
24
|
|
30
|
-
|
31
|
-
shape = d["shape"]
|
32
|
-
dtype = d["dtype"]
|
33
|
-
buffer = b64decode(d["data"].encode())
|
34
|
-
return np.frombuffer(buffer, dtype=dtype).reshape(shape)
|
25
|
+
return _wrapper
|
35
26
|
|
36
27
|
|
37
|
-
def custom_encode(o):
|
38
|
-
|
39
|
-
|
28
|
+
def custom_encode(o) -> dict:
|
29
|
+
for name, type_, support in _BINDINGS:
|
30
|
+
if isinstance(o, type_):
|
31
|
+
doc = support.encode(o)
|
32
|
+
doc["__TYPE__"] = name
|
33
|
+
return doc
|
40
34
|
raise TypeError(f"Object of type {o.__class__.__name__} is not JSON serializable")
|
41
35
|
|
42
36
|
|
43
|
-
def custom_decode(d):
|
37
|
+
def custom_decode(d: dict):
|
44
38
|
__type__ = d.get("__TYPE__")
|
45
39
|
if __type__ is None:
|
46
40
|
return d
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
41
|
+
|
42
|
+
for name, _, support in _BINDINGS:
|
43
|
+
if __type__ == name:
|
44
|
+
return support.decode(d)
|
45
|
+
return d
|
51
46
|
|
52
47
|
|
53
48
|
dump = partial(json.dump, default=custom_encode)
|
@@ -55,3 +50,36 @@ dumps = partial(json.dumps, default=custom_encode)
|
|
55
50
|
|
56
51
|
load = partial(json.load, object_hook=custom_decode)
|
57
52
|
loads = partial(json.loads, object_hook=custom_decode)
|
53
|
+
|
54
|
+
|
55
|
+
@bind("bytes", bytes)
|
56
|
+
class BytesSupport:
|
57
|
+
|
58
|
+
def encode(self, o: bytes) -> dict:
|
59
|
+
return {
|
60
|
+
"data": b64encode(o).decode(),
|
61
|
+
}
|
62
|
+
|
63
|
+
def decode(self, d: dict) -> bytes:
|
64
|
+
return b64decode(d["data"])
|
65
|
+
|
66
|
+
|
67
|
+
@bind("numpy", np.ndarray)
|
68
|
+
class NumpySupport:
|
69
|
+
|
70
|
+
def encode(self, a):
|
71
|
+
shape = a.shape
|
72
|
+
dtype = a.dtype
|
73
|
+
data = a.tobytes(order="C")
|
74
|
+
data = b64encode(data).decode()
|
75
|
+
return {
|
76
|
+
"data": data,
|
77
|
+
"shape": shape,
|
78
|
+
"dtype": str(dtype),
|
79
|
+
}
|
80
|
+
|
81
|
+
def decode(self, d):
|
82
|
+
shape = d["shape"]
|
83
|
+
dtype = d["dtype"]
|
84
|
+
buffer = b64decode(d["data"].encode())
|
85
|
+
return np.frombuffer(buffer, dtype=dtype).reshape(shape)
|
libentry/utils.py
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
|
3
|
+
__author__ = "xi"
|
4
|
+
__all__ = [
|
5
|
+
"Timer"
|
6
|
+
]
|
7
|
+
|
8
|
+
import time
|
9
|
+
|
10
|
+
|
11
|
+
class Timer:
|
12
|
+
|
13
|
+
def __init__(self):
|
14
|
+
self.start_time = None
|
15
|
+
self.end_time = None
|
16
|
+
self.cost = None
|
17
|
+
|
18
|
+
def __enter__(self):
|
19
|
+
self.start()
|
20
|
+
return self
|
21
|
+
|
22
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
23
|
+
self.end()
|
24
|
+
|
25
|
+
def start(self):
|
26
|
+
self.start_time = time.perf_counter()
|
27
|
+
self.end_time = None
|
28
|
+
self.cost = None
|
29
|
+
|
30
|
+
def end(self):
|
31
|
+
if self.start_time is None:
|
32
|
+
raise RuntimeError("The timer has not started yet.")
|
33
|
+
self.end_time = time.perf_counter()
|
34
|
+
self.cost = self.end_time - self.start_time
|
@@ -1,13 +1,14 @@
|
|
1
1
|
libentry/__init__.py,sha256=ko2YBIIx5H3dD0tedBkialzJGEDczFaP_PZmT1cIlak,148
|
2
|
-
libentry/api.py,sha256=
|
2
|
+
libentry/api.py,sha256=yB5iquRa4RZO0XMcs1Xx8mjI6dQcKJ0j4r9C4JB-j2s,23931
|
3
3
|
libentry/argparse.py,sha256=NxzXV-jBN51ReZsNs5aeyOfzwYQ5A5nJ95rWoa-FYCs,10415
|
4
4
|
libentry/dataclasses.py,sha256=AQV2PuxplJCwGZ5HKX72U-z-POUhTdy3XtpEK9KNIGQ,4541
|
5
5
|
libentry/executor.py,sha256=cTV0WxJi0nU1TP-cOwmeodN8DD6L1691M2HIQsJtGrU,6582
|
6
6
|
libentry/experiment.py,sha256=ejgAHDXWIe9x4haUzIFuz1WasLY0_aD1z_vyEVGjTu8,4922
|
7
|
-
libentry/json.py,sha256=
|
7
|
+
libentry/json.py,sha256=Rigg8H3oWooI9bNfIpx9mSOcoc3aTigy_-BHiPIv8kY,1821
|
8
8
|
libentry/logging.py,sha256=IiYoCUzm8XTK1fduA-NA0FI2Qz_m81NEPV3d3tEfgdI,1349
|
9
9
|
libentry/schema.py,sha256=o6JcdR00Yj4_Qjmlo100OlQpMVnl0PgvvwVVrL9limw,8268
|
10
10
|
libentry/test_api.py,sha256=Xw7B7sH6g1iCTV5sFzyBF3JAJzeOr9xg0AyezTNsnIk,4452
|
11
|
+
libentry/utils.py,sha256=O7P6GadtUIjq0N2IZH7PhHZDUM3NebzcqyDqytet7CM,683
|
11
12
|
libentry/service/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
|
12
13
|
libentry/service/common.py,sha256=OVaW2afgKA6YqstJmtnprBCqQEUZEWotZ6tHavmJJeU,42
|
13
14
|
libentry/service/flask.py,sha256=Alpsix01ROqI28k-dabD8wJlWAWs-ObNc1nJ-LxOXn4,13349
|
@@ -15,10 +16,10 @@ libentry/service/list.py,sha256=ElHWhTgShGOhaxMUEwVbMXos0NQKjHsODboiQ-3AMwE,1397
|
|
15
16
|
libentry/service/running.py,sha256=FrPJoJX6wYxcHIysoatAxhW3LajCCm0Gx6l7__6sULQ,5105
|
16
17
|
libentry/service/start.py,sha256=mZT7b9rVULvzy9GTZwxWnciCHgv9dbGN2JbxM60OMn4,1270
|
17
18
|
libentry/service/stop.py,sha256=wOpwZgrEJ7QirntfvibGq-XsTC6b3ELhzRW2zezh-0s,1187
|
18
|
-
libentry-1.
|
19
|
-
libentry-1.
|
20
|
-
libentry-1.
|
21
|
-
libentry-1.
|
22
|
-
libentry-1.
|
23
|
-
libentry-1.
|
24
|
-
libentry-1.
|
19
|
+
libentry-1.22.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
20
|
+
libentry-1.22.dist-info/METADATA,sha256=MlKCJZtUY5SMDcf4HmUyZKvPxUGyJfsBqdrWqoN7ByM,811
|
21
|
+
libentry-1.22.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
22
|
+
libentry-1.22.dist-info/entry_points.txt,sha256=vgHmJZhM-kqM7U9S179UwDD3pM232tpzJ5NntncXi_8,62
|
23
|
+
libentry-1.22.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
|
24
|
+
libentry-1.22.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
25
|
+
libentry-1.22.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|