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 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
- body = json.dumps(json_data) if json_data is not None else None
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
- body = json.dumps(json_data) if json_data is not None else None
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
- def decode_ndarray(d):
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
- if isinstance(o, np.ndarray):
39
- return encode_ndarray(o)
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
- if __type__ == "numpy":
48
- return decode_ndarray(d)
49
- else:
50
- return d
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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: libentry
3
- Version: 1.21.3
3
+ Version: 1.22
4
4
  Summary: Entries for experimental utilities.
5
5
  Home-page: https://github.com/XoriieInpottn/libentry
6
6
  Author: xi
@@ -1,13 +1,14 @@
1
1
  libentry/__init__.py,sha256=ko2YBIIx5H3dD0tedBkialzJGEDczFaP_PZmT1cIlak,148
2
- libentry/api.py,sha256=ei67QL_PEMs1J_utCuh5MifPbAw17BOYnaYtc8d35UY,22923
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=1-Kv5ZRb5dBrOTU84n6sZtYZV3xE-O6wEt_--ynbSaU,1209
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.21.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
19
- libentry-1.21.3.dist-info/METADATA,sha256=43wuxNjrLdOaLoW5E55_JEMhGAPAAVTFe5WltenN7L0,813
20
- libentry-1.21.3.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
21
- libentry-1.21.3.dist-info/entry_points.txt,sha256=vgHmJZhM-kqM7U9S179UwDD3pM232tpzJ5NntncXi_8,62
22
- libentry-1.21.3.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
23
- libentry-1.21.3.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
24
- libentry-1.21.3.dist-info/RECORD,,
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,,