libentry 1.25__py3-none-any.whl → 1.26__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/client.py CHANGED
@@ -9,7 +9,7 @@ from threading import Semaphore, Thread
9
9
  from time import sleep
10
10
  from types import GeneratorType
11
11
  from typing import Any, Dict, Iterable, List, Optional, Tuple, Type, Union
12
- from urllib.parse import urlencode, urljoin
12
+ from urllib.parse import urlencode
13
13
 
14
14
  import httpx
15
15
  from pydantic import BaseModel, TypeAdapter
@@ -371,7 +371,7 @@ class APIClient(SubroutineMixIn, MCPMixIn):
371
371
  raise err
372
372
 
373
373
  def _http_request(self, request: HTTPRequest, timeout: float) -> HTTPResponse:
374
- full_url = urljoin(self.base_url, request.path)
374
+ full_url = self.base_url.rstrip("/") + "/" + request.path.lstrip("/")
375
375
  headers = (
376
376
  {**self.headers}
377
377
  if request.options.headers is None else
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, Type, Union
13
+ from typing import Any, Callable, Dict, Generator, Iterable, List, Literal, Optional, Tuple, Type, Union
14
14
 
15
15
  from flask import Flask, request as flask_request
16
16
  from pydantic import BaseModel, Field, TypeAdapter
@@ -805,9 +805,11 @@ class FlaskServer(Flask):
805
805
  logger.info("Initializing Flask application.")
806
806
  existing_routes = {}
807
807
 
808
- routes = self._create_routes(self.service)
809
- self.service_routes.update(routes)
810
- existing_routes.update(self.service_routes)
808
+ input_services = self.service if isinstance(self.service, (List, Tuple)) else [self.service]
809
+ for input_service in input_services:
810
+ routes = self._create_routes(input_service)
811
+ self.service_routes.update(routes)
812
+ existing_routes.update(self.service_routes)
811
813
 
812
814
  for builtin_service in self.builtin_services:
813
815
  routes = self._create_routes(builtin_service, existing_routes)
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
3
+ Version: 1.26
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
- libentry/mcp/client.py,sha256=3HmKAsFenPlDk1lfSdXL9GJwfCSU92uQS04zvZGeJfQ,23065
16
- libentry/mcp/service.py,sha256=VTLA9dS85NJ64OCf1zBKLWvvE9l76I-U8WV5crCmBlM,37943
15
+ libentry/mcp/client.py,sha256=qFbigNIOJvEf8ZICN2K8nnmVcITIzDhJgaw3c0P-WXM,23078
16
+ libentry/mcp/service.py,sha256=PpdQBxqKPiZ2tpnsqDYiC29_yjMjK9J3VWynn4uvpVg,38109
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.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
- libentry-1.25.dist-info/METADATA,sha256=mlgd255AfSGCHpiUuPqHMVipyfRm-Xal71qb5dQAJlg,1133
27
- libentry-1.25.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
- libentry-1.25.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
29
- libentry-1.25.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
30
- libentry-1.25.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
- libentry-1.25.dist-info/RECORD,,
25
+ libentry-1.26.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
+ libentry-1.26.dist-info/METADATA,sha256=FhTlnziZK-JqX2iRA3i4p0Oz9cQviwQV1dwmhz6Cxs0,1133
27
+ libentry-1.26.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
+ libentry-1.26.dist-info/entry_points.txt,sha256=1v_nLVDsjvVJp9SWhl4ef2zZrsLTBtFWgrYFgqvQBgc,61
29
+ libentry-1.26.dist-info/top_level.txt,sha256=u2uF6-X5fn2Erf9PYXOg_6tntPqTpyT-yzUZrltEd6I,9
30
+ libentry-1.26.dist-info/zip-safe,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
31
+ libentry-1.26.dist-info/RECORD,,