libentry 1.25.1__py3-none-any.whl → 1.27__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/mcp/service.py CHANGED
@@ -10,7 +10,7 @@ from dataclasses import dataclass
10
10
  from queue import Empty, Queue
11
11
  from threading import Lock
12
12
  from types import GeneratorType
13
- from typing import Any, Callable, Dict, Generator, Iterable, List, Literal, Optional, Tuple, Type, Union
13
+ from typing import Any, Callable, Dict, Generator, Iterable, List, Literal, Optional, Tuple, Union
14
14
 
15
15
  from flask import Flask, request as flask_request
16
16
  from pydantic import BaseModel, Field, TypeAdapter
@@ -891,19 +891,41 @@ class GunicornApplication(BaseApplication):
891
891
 
892
892
  def load(self):
893
893
  logger.info("Initializing the service.")
894
- if isinstance(self.service_type, type) or callable(self.service_type):
895
- service = self.service_type(self.service_config) if self.service_config else self.service_type()
896
- elif self.service_config is None:
894
+ if isinstance(self.service_type, (List, Tuple)):
895
+ if isinstance(self.service_config, (List, Tuple)) and len(self.service_config) == len(self.service_type):
896
+ service = [
897
+ self._create_service(t, c)
898
+ for t, c in zip(self.service_type, self.service_config)
899
+ ]
900
+ elif self.service_config is None:
901
+ service = [
902
+ self._create_service(t, self.service_config)
903
+ for t in self.service_type
904
+ ]
905
+ else:
906
+ raise RuntimeError(
907
+ f"You are going to run {len(self.service_type)} services. "
908
+ "In the multiple service mode, every `service_type` requires a `service_config` object."
909
+ )
910
+ else:
911
+ service = self._create_service(self.service_type, self.service_config)
912
+ logger.info("Service initialized.")
913
+
914
+ return FlaskServer(service)
915
+
916
+ @staticmethod
917
+ def _create_service(service_type, service_config):
918
+ if isinstance(service_type, type) or callable(service_type):
919
+ service = service_type(service_config) if service_config else service_type()
920
+ elif service_config is None:
897
921
  logger.warning(
898
922
  "Be careful! It is not recommended to start the server from a service instance. "
899
923
  "Use service_type and service_config instead."
900
924
  )
901
- service = self.service_type
925
+ service = service_type
902
926
  else:
903
- raise TypeError(f"Invalid service type \"{type(self.service_type)}\".")
904
- logger.info("Service initialized.")
905
-
906
- return FlaskServer(service)
927
+ raise TypeError(f"Invalid service type \"{type(service_type)}\".")
928
+ return service
907
929
 
908
930
 
909
931
  class RunServiceConfig(BaseModel):
@@ -969,7 +991,7 @@ class RunServiceConfig(BaseModel):
969
991
 
970
992
 
971
993
  def run_service(
972
- service_type: Union[Type, Callable],
994
+ service_type: Union[Union[type, Callable], List, Tuple],
973
995
  service_config=None,
974
996
  run_config: Optional[RunServiceConfig] = None,
975
997
  *,
libentry/test_api.py CHANGED
@@ -11,7 +11,8 @@ from typing import Literal, Optional
11
11
 
12
12
  from pydantic import BaseModel
13
13
 
14
- from libentry.api import APIClient
14
+ from libentry.mcp.client import APIClient
15
+ from libentry.mcp.types import HTTPOptions
15
16
 
16
17
 
17
18
  class TestRequest(BaseModel):
@@ -49,14 +50,13 @@ def test(request: TestRequest):
49
50
  if request.method == "GET":
50
51
  response = APIClient().get(
51
52
  request.url,
52
- **kwargs
53
+ HTTPOptions(**kwargs)
53
54
  )
54
55
  else:
55
56
  response = APIClient().post(
56
57
  request.url,
57
58
  request.data,
58
- stream=request.stream,
59
- **kwargs
59
+ HTTPOptions(stream=request.stream, **kwargs)
60
60
  )
61
61
  if not request.stream:
62
62
  t = time() - t
libentry/utils.py CHANGED
@@ -2,10 +2,14 @@
2
2
 
3
3
  __author__ = "xi"
4
4
  __all__ = [
5
- "Timer"
5
+ "Timer",
6
+ "TimedLRUCache",
6
7
  ]
7
8
 
9
+ import threading
8
10
  import time
11
+ from collections import OrderedDict
12
+ from functools import wraps
9
13
 
10
14
 
11
15
  class Timer:
@@ -32,3 +36,42 @@ class Timer:
32
36
  raise RuntimeError("The timer has not started yet.")
33
37
  self.end_time = time.perf_counter()
34
38
  self.cost = self.end_time - self.start_time
39
+
40
+
41
+ class TimedLRUCache:
42
+
43
+ def __init__(self, max_size: int = 256, timeout: float = 12):
44
+ self.maxsize = max_size
45
+ self.timeout = timeout # seconds
46
+
47
+ self.lock = threading.Lock()
48
+ self.cache = OrderedDict()
49
+
50
+ def __call__(self, func):
51
+ @wraps(func)
52
+ def wrapped(*args, **kwargs):
53
+ key = (args, frozenset(kwargs.items()))
54
+ now = time.time()
55
+
56
+ with self.lock:
57
+ # clean expired items
58
+ if key in self.cache:
59
+ result, timestamp = self.cache[key]
60
+ if now - timestamp < self.timeout:
61
+ self.cache.move_to_end(key)
62
+ return result
63
+ else:
64
+ del self.cache[key] # expired
65
+
66
+ # compute new result
67
+ result = func(*args, **kwargs)
68
+ self.cache[key] = (result, now)
69
+ self.cache.move_to_end(key)
70
+
71
+ # exceed the max size
72
+ if len(self.cache) > self.maxsize:
73
+ self.cache.popitem(last=False) # remove the oldest item
74
+
75
+ return result
76
+
77
+ return wrapped
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: libentry
3
- Version: 1.25.1
3
+ Version: 1.27
4
4
  Summary: Entries for experimental utilities.
5
5
  Home-page: https://github.com/XoriieInpottn/libentry
6
6
  Author: xi
@@ -8,12 +8,12 @@ libentry/json.py,sha256=gTjogVG6eGUMkVrjilKkpFC8ZkElGAyZIutO7mbmSzg,1956
8
8
  libentry/logging.py,sha256=IiYoCUzm8XTK1fduA-NA0FI2Qz_m81NEPV3d3tEfgdI,1349
9
9
  libentry/resource.py,sha256=qAPXF7RzRYeCM4xWft6XR3SYk7lEiQ6ymOHbpNoi0mQ,1821
10
10
  libentry/schema.py,sha256=40SOhCF_eytWOF47MWKCRHKHl_lCaQVetx1Af62PkiI,10439
11
- libentry/test_api.py,sha256=Xw7B7sH6g1iCTV5sFzyBF3JAJzeOr9xg0AyezTNsnIk,4452
12
- libentry/utils.py,sha256=O7P6GadtUIjq0N2IZH7PhHZDUM3NebzcqyDqytet7CM,683
11
+ libentry/test_api.py,sha256=bs7P8gveLtuUvHxrpujSrfuYqLVJ3fOXVg_MZnZxoJ4,4504
12
+ libentry/utils.py,sha256=vCm6UyAlibnPOlPJHZO57u3TXhw5PZmGM5_vBAPUnB4,1981
13
13
  libentry/mcp/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
14
14
  libentry/mcp/api.py,sha256=GDErVCz_hh_ZeMxLS8bTPyBUhCTHw3Mm-nGFMV2W2yo,3669
15
15
  libentry/mcp/client.py,sha256=qFbigNIOJvEf8ZICN2K8nnmVcITIzDhJgaw3c0P-WXM,23078
16
- libentry/mcp/service.py,sha256=PpdQBxqKPiZ2tpnsqDYiC29_yjMjK9J3VWynn4uvpVg,38109
16
+ libentry/mcp/service.py,sha256=YMzP9sTR6RaeguwbwapFZFcc7MjKuDDfpeXSCD09Xzg,39081
17
17
  libentry/mcp/types.py,sha256=aAoVO4jjqEvDzNneuZapmRYonLLnGsbcLoypVyRNNYg,12389
18
18
  libentry/service/__init__.py,sha256=1oLL20yLB1GL9IbFiZD8OReDqiCpFr-yetIR6x1cNkI,23
19
19
  libentry/service/common.py,sha256=OVaW2afgKA6YqstJmtnprBCqQEUZEWotZ6tHavmJJeU,42
@@ -22,10 +22,10 @@ libentry/service/list.py,sha256=ElHWhTgShGOhaxMUEwVbMXos0NQKjHsODboiQ-3AMwE,1397
22
22
  libentry/service/running.py,sha256=FrPJoJX6wYxcHIysoatAxhW3LajCCm0Gx6l7__6sULQ,5105
23
23
  libentry/service/start.py,sha256=mZT7b9rVULvzy9GTZwxWnciCHgv9dbGN2JbxM60OMn4,1270
24
24
  libentry/service/stop.py,sha256=wOpwZgrEJ7QirntfvibGq-XsTC6b3ELhzRW2zezh-0s,1187
25
- libentry-1.25.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
- libentry-1.25.1.dist-info/METADATA,sha256=7HVCqasAkkqvvXhodRtTmaoZTG4FC70Q6CxsgZWnC8U,1135
27
- libentry-1.25.1.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
- libentry-1.25.1.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
29
- libentry-1.25.1.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
30
- libentry-1.25.1.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
- libentry-1.25.1.dist-info/RECORD,,
25
+ libentry-1.27.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
+ libentry-1.27.dist-info/METADATA,sha256=4Kmb2RNxxAYb26wbovxkx8haDAaW7tBg_JEuxPwkwuI,1133
27
+ libentry-1.27.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
+ libentry-1.27.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
29
+ libentry-1.27.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
30
+ libentry-1.27.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
+ libentry-1.27.dist-info/RECORD,,