stores 0.1.3__tar.gz → 0.1.5__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.
- {stores-0.1.3 → stores-0.1.5}/PKG-INFO +1 -1
- {stores-0.1.3 → stores-0.1.5}/pyproject.toml +1 -1
- {stores-0.1.3 → stores-0.1.5}/stores/indexes/base_index.py +12 -3
- {stores-0.1.3 → stores-0.1.5}/stores/indexes/index.py +2 -0
- {stores-0.1.3 → stores-0.1.5}/stores/indexes/local_index.py +10 -1
- {stores-0.1.3 → stores-0.1.5}/stores/indexes/remote_index.py +8 -1
- {stores-0.1.3 → stores-0.1.5}/stores/indexes/venv_utils.py +38 -13
- {stores-0.1.3 → stores-0.1.5}/tests/test_indexes/test_venv_utils.py +4 -2
- {stores-0.1.3 → stores-0.1.5}/uv.lock +1 -1
- {stores-0.1.3 → stores-0.1.5}/.gitignore +0 -0
- {stores-0.1.3 → stores-0.1.5}/.python-version +0 -0
- {stores-0.1.3 → stores-0.1.5}/LICENSE +0 -0
- {stores-0.1.3 → stores-0.1.5}/README.md +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/README.md +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/anthropic_api.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/google_gemini_auto_call.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/google_gemini_manual_call.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/langchain_w_tool_calling.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/langgraph_agent.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/litellm_w_tool_calling.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/llamaindex_agent.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/openai_agent.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/openai_chat_completions.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/examples/quickstarts/openai_responses.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/run_complex.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/run_remote_tool.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/stores/__init__.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/stores/constants.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/stores/format.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/stores/indexes/__init__.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/stores/parse.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/stores/utils.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/README.md +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index/hello/__init__.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index/tools.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index/tools.toml +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_custom_class/foo.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_custom_class/tools.toml +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_function_error/foo.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_function_error/tools.toml +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_w_deps/mock_index/__init__.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_w_deps/pyproject.toml +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_w_deps/requirements.txt +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/mock_index_w_deps/tools.toml +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_format/conftest.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_format/test_format.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_indexes/conftest.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_indexes/test_base_index.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_indexes/test_index.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_indexes/test_local_index.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_indexes/test_remote_index.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_parse/conftest.py +0 -0
- {stores-0.1.3 → stores-0.1.5}/tests/test_parse/test_parse.py +0 -0
@@ -250,6 +250,11 @@ class BaseIndex:
|
|
250
250
|
return {tool.__name__: tool for tool in self.tools}
|
251
251
|
|
252
252
|
def execute(self, toolname: str, kwargs: dict | None = None):
|
253
|
+
loop = asyncio.new_event_loop()
|
254
|
+
asyncio.set_event_loop(loop)
|
255
|
+
return loop.run_until_complete(self.async_execute(toolname, kwargs))
|
256
|
+
|
257
|
+
async def async_execute(self, toolname: str, kwargs: dict | None = None):
|
253
258
|
kwargs = kwargs or {}
|
254
259
|
|
255
260
|
# Use regex since we need to match cases where we perform
|
@@ -269,9 +274,7 @@ class BaseIndex:
|
|
269
274
|
|
270
275
|
tool = self.tools_dict[toolname]
|
271
276
|
if inspect.iscoroutinefunction(tool):
|
272
|
-
|
273
|
-
asyncio.set_event_loop(loop)
|
274
|
-
return loop.run_until_complete(tool(**kwargs))
|
277
|
+
return await tool(**kwargs)
|
275
278
|
else:
|
276
279
|
return tool(**kwargs)
|
277
280
|
|
@@ -279,5 +282,11 @@ class BaseIndex:
|
|
279
282
|
toolcall = llm_parse_json(msg, keys=["toolname", "kwargs"])
|
280
283
|
return self.execute(toolcall.get("toolname"), toolcall.get("kwargs"))
|
281
284
|
|
285
|
+
async def async_parse_and_execute(self, msg: str):
|
286
|
+
toolcall = llm_parse_json(msg, keys=["toolname", "kwargs"])
|
287
|
+
return await self.async_execute(
|
288
|
+
toolcall.get("toolname"), toolcall.get("kwargs")
|
289
|
+
)
|
290
|
+
|
282
291
|
def format_tools(self, provider: ProviderFormat):
|
283
292
|
return format_tools(self.tools, provider)
|
@@ -19,6 +19,7 @@ class Index(BaseIndex):
|
|
19
19
|
env_var: dict[str, dict] | None = None,
|
20
20
|
cache_dir: Optional[os.PathLike] = None,
|
21
21
|
reset_cache=False,
|
22
|
+
sys_executable: str | None = None,
|
22
23
|
):
|
23
24
|
self.env_var = env_var or {}
|
24
25
|
tools = tools or []
|
@@ -44,6 +45,7 @@ class Index(BaseIndex):
|
|
44
45
|
env_var=self.env_var.get(index_name),
|
45
46
|
cache_dir=cache_dir,
|
46
47
|
reset_cache=reset_cache,
|
48
|
+
sys_executable=sys_executable,
|
47
49
|
)
|
48
50
|
except Exception:
|
49
51
|
logger.warning(
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import importlib
|
2
2
|
import logging
|
3
3
|
import os
|
4
|
+
import subprocess
|
4
5
|
import sys
|
5
6
|
import venv
|
6
7
|
from pathlib import Path
|
@@ -25,6 +26,7 @@ class LocalIndex(BaseIndex):
|
|
25
26
|
index_folder: os.PathLike,
|
26
27
|
create_venv: bool = False,
|
27
28
|
env_var: dict | None = None,
|
29
|
+
sys_executable: str | None = None,
|
28
30
|
):
|
29
31
|
self.index_folder = Path(index_folder)
|
30
32
|
self.env_var = env_var or {}
|
@@ -38,7 +40,14 @@ class LocalIndex(BaseIndex):
|
|
38
40
|
# Create venv and install deps
|
39
41
|
self.venv = self.index_folder / VENV_NAME
|
40
42
|
if not self.venv.exists():
|
41
|
-
|
43
|
+
if sys_executable:
|
44
|
+
subprocess.run(
|
45
|
+
[sys_executable, "-m", "venv", str(self.venv)], check=True
|
46
|
+
)
|
47
|
+
else:
|
48
|
+
venv.create(
|
49
|
+
self.venv, symlinks=True, with_pip=True, upgrade_deps=True
|
50
|
+
)
|
42
51
|
install_venv_deps(self.index_folder)
|
43
52
|
# Initialize tools
|
44
53
|
tools = init_venv_tools(self.index_folder, self.env_var)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import json
|
2
2
|
import logging
|
3
3
|
import shutil
|
4
|
+
import subprocess
|
4
5
|
import venv
|
5
6
|
from os import PathLike
|
6
7
|
from pathlib import Path
|
@@ -52,6 +53,7 @@ class RemoteIndex(BaseIndex):
|
|
52
53
|
env_var: dict | None = None,
|
53
54
|
cache_dir: Optional[PathLike] = None,
|
54
55
|
reset_cache=False,
|
56
|
+
sys_executable: str | None = None,
|
55
57
|
):
|
56
58
|
self.index_id = index_id
|
57
59
|
if cache_dir is None:
|
@@ -89,7 +91,12 @@ class RemoteIndex(BaseIndex):
|
|
89
91
|
# Create venv and install deps
|
90
92
|
self.venv = self.index_folder / VENV_NAME
|
91
93
|
if not self.venv.exists():
|
92
|
-
|
94
|
+
if sys_executable:
|
95
|
+
subprocess.run(
|
96
|
+
[sys_executable, "-m", "venv", str(self.venv)], check=True
|
97
|
+
)
|
98
|
+
else:
|
99
|
+
venv.create(self.venv, symlinks=True, with_pip=True, upgrade_deps=True)
|
93
100
|
install_venv_deps(self.index_folder)
|
94
101
|
# Initialize tools
|
95
102
|
tools = init_venv_tools(self.index_folder, self.env_var)
|
@@ -28,11 +28,35 @@ logger.setLevel(logging.INFO)
|
|
28
28
|
HASH_FILE = ".deps_hash"
|
29
29
|
|
30
30
|
|
31
|
-
|
32
|
-
"pyproject.toml"
|
33
|
-
"setup.py"
|
34
|
-
"requirements.txt"
|
35
|
-
|
31
|
+
SUPPORTED_CONFIGS = [
|
32
|
+
"pyproject.toml",
|
33
|
+
"setup.py",
|
34
|
+
"requirements.txt",
|
35
|
+
]
|
36
|
+
|
37
|
+
|
38
|
+
def get_pip_command(venv_path: os.PathLike, config_file: str) -> list[str]:
|
39
|
+
venv_path = Path(venv_path).resolve()
|
40
|
+
if os.name == "nt":
|
41
|
+
pip_path = venv_path / "Scripts" / "pip.exe"
|
42
|
+
else:
|
43
|
+
pip_path = venv_path / "bin" / "pip"
|
44
|
+
|
45
|
+
if config_file in {"pyproject.toml", "setup.py"}:
|
46
|
+
return [str(pip_path), "install", "."]
|
47
|
+
elif config_file == "requirements.txt":
|
48
|
+
return [str(pip_path), "install", "-r", "requirements.txt"]
|
49
|
+
else:
|
50
|
+
raise ValueError(f"Unsupported config file: {config_file}")
|
51
|
+
|
52
|
+
|
53
|
+
def get_python_command(venv_path: os.PathLike) -> list[str]:
|
54
|
+
venv_path = Path(venv_path).resolve()
|
55
|
+
if os.name == "nt":
|
56
|
+
executable = venv_path / "Scripts" / "python.exe"
|
57
|
+
else:
|
58
|
+
executable = venv_path / "bin" / "python"
|
59
|
+
return str(executable)
|
36
60
|
|
37
61
|
|
38
62
|
def has_installed(config_path: os.PathLike):
|
@@ -63,18 +87,19 @@ def write_hash(config_path: os.PathLike):
|
|
63
87
|
def install_venv_deps(index_folder: os.PathLike):
|
64
88
|
index_folder = Path(index_folder)
|
65
89
|
|
66
|
-
for config_file
|
90
|
+
for config_file in SUPPORTED_CONFIGS:
|
67
91
|
config_path = index_folder / config_file
|
68
92
|
if config_path.exists():
|
69
93
|
# Check if already installed
|
70
94
|
if has_installed(config_path):
|
71
95
|
return "Already installed"
|
96
|
+
pip_command = get_pip_command(index_folder / VENV_NAME, config_file)
|
72
97
|
subprocess.check_call(
|
73
|
-
|
98
|
+
pip_command,
|
74
99
|
cwd=index_folder,
|
75
100
|
)
|
76
101
|
write_hash(config_path)
|
77
|
-
message = f
|
102
|
+
message = f'Installed with "{" ".join(pip_command)}"'
|
78
103
|
logger.info(message)
|
79
104
|
return message
|
80
105
|
|
@@ -201,10 +226,10 @@ except Exception as e:
|
|
201
226
|
pickle.dump({{"ok": False, "error": err}}, sys.stdout.buffer)
|
202
227
|
"""
|
203
228
|
result = subprocess.run(
|
204
|
-
[
|
229
|
+
[get_python_command(Path(index_folder) / venv), "-c", runner],
|
205
230
|
capture_output=True,
|
206
231
|
cwd=index_folder,
|
207
|
-
env=env_var,
|
232
|
+
env=env_var or None,
|
208
233
|
)
|
209
234
|
try:
|
210
235
|
response = pickle.loads(result.stdout)
|
@@ -380,11 +405,11 @@ sock = socket.create_connection(("localhost", {port}))
|
|
380
405
|
sock.sendall(response.encode("utf-8"))
|
381
406
|
sock.close()
|
382
407
|
"""
|
383
|
-
subprocess.run(
|
384
|
-
[
|
408
|
+
result = subprocess.run(
|
409
|
+
[get_python_command(Path(index_folder) / venv), "-c", runner],
|
385
410
|
input=payload,
|
386
411
|
capture_output=True,
|
387
|
-
env=env_var,
|
412
|
+
env=env_var or None,
|
388
413
|
)
|
389
414
|
|
390
415
|
t.join()
|
@@ -35,9 +35,11 @@ async def test_install_venv_deps(remote_index_folder):
|
|
35
35
|
result = venv_utils.install_venv_deps(remote_index_folder)
|
36
36
|
assert (remote_index_folder / venv_utils.HASH_FILE).exists()
|
37
37
|
|
38
|
-
for config_file
|
38
|
+
for config_file in venv_utils.SUPPORTED_CONFIGS:
|
39
39
|
if (remote_index_folder / config_file).exists():
|
40
|
-
assert result.endswith(
|
40
|
+
assert result.endswith(
|
41
|
+
f'"{" ".join(venv_utils.get_pip_command(venv_folder, config_file))}"'
|
42
|
+
)
|
41
43
|
assert venv_utils.has_installed(remote_index_folder / config_file)
|
42
44
|
break
|
43
45
|
|
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
|
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
|
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
|
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
|