stores 0.1.1__tar.gz → 0.1.3__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.
Files changed (53) hide show
  1. {stores-0.1.1 → stores-0.1.3}/PKG-INFO +1 -1
  2. {stores-0.1.1 → stores-0.1.3}/pyproject.toml +1 -1
  3. stores-0.1.3/run_remote_tool.py +8 -0
  4. {stores-0.1.1 → stores-0.1.3}/stores/indexes/index.py +7 -2
  5. {stores-0.1.1 → stores-0.1.3}/stores/indexes/remote_index.py +22 -2
  6. {stores-0.1.1 → stores-0.1.3}/stores/indexes/venv_utils.py +34 -15
  7. {stores-0.1.1 → stores-0.1.3}/tests/test_indexes/test_remote_index.py +9 -0
  8. {stores-0.1.1 → stores-0.1.3}/uv.lock +1 -1
  9. {stores-0.1.1 → stores-0.1.3}/.gitignore +0 -0
  10. {stores-0.1.1 → stores-0.1.3}/.python-version +0 -0
  11. {stores-0.1.1 → stores-0.1.3}/LICENSE +0 -0
  12. {stores-0.1.1 → stores-0.1.3}/README.md +0 -0
  13. {stores-0.1.1 → stores-0.1.3}/examples/README.md +0 -0
  14. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/anthropic_api.py +0 -0
  15. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/google_gemini_auto_call.py +0 -0
  16. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/google_gemini_manual_call.py +0 -0
  17. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/langchain_w_tool_calling.py +0 -0
  18. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/langgraph_agent.py +0 -0
  19. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/litellm_w_tool_calling.py +0 -0
  20. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/llamaindex_agent.py +0 -0
  21. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/openai_agent.py +0 -0
  22. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/openai_chat_completions.py +0 -0
  23. {stores-0.1.1 → stores-0.1.3}/examples/quickstarts/openai_responses.py +0 -0
  24. {stores-0.1.1 → stores-0.1.3}/run_complex.py +0 -0
  25. {stores-0.1.1 → stores-0.1.3}/stores/__init__.py +0 -0
  26. {stores-0.1.1 → stores-0.1.3}/stores/constants.py +0 -0
  27. {stores-0.1.1 → stores-0.1.3}/stores/format.py +0 -0
  28. {stores-0.1.1 → stores-0.1.3}/stores/indexes/__init__.py +0 -0
  29. {stores-0.1.1 → stores-0.1.3}/stores/indexes/base_index.py +0 -0
  30. {stores-0.1.1 → stores-0.1.3}/stores/indexes/local_index.py +0 -0
  31. {stores-0.1.1 → stores-0.1.3}/stores/parse.py +0 -0
  32. {stores-0.1.1 → stores-0.1.3}/stores/utils.py +0 -0
  33. {stores-0.1.1 → stores-0.1.3}/tests/README.md +0 -0
  34. {stores-0.1.1 → stores-0.1.3}/tests/mock_index/hello/__init__.py +0 -0
  35. {stores-0.1.1 → stores-0.1.3}/tests/mock_index/tools.py +0 -0
  36. {stores-0.1.1 → stores-0.1.3}/tests/mock_index/tools.toml +0 -0
  37. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_custom_class/foo.py +0 -0
  38. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_custom_class/tools.toml +0 -0
  39. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_function_error/foo.py +0 -0
  40. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_function_error/tools.toml +0 -0
  41. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_w_deps/mock_index/__init__.py +0 -0
  42. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_w_deps/pyproject.toml +0 -0
  43. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_w_deps/requirements.txt +0 -0
  44. {stores-0.1.1 → stores-0.1.3}/tests/mock_index_w_deps/tools.toml +0 -0
  45. {stores-0.1.1 → stores-0.1.3}/tests/test_format/conftest.py +0 -0
  46. {stores-0.1.1 → stores-0.1.3}/tests/test_format/test_format.py +0 -0
  47. {stores-0.1.1 → stores-0.1.3}/tests/test_indexes/conftest.py +0 -0
  48. {stores-0.1.1 → stores-0.1.3}/tests/test_indexes/test_base_index.py +0 -0
  49. {stores-0.1.1 → stores-0.1.3}/tests/test_indexes/test_index.py +0 -0
  50. {stores-0.1.1 → stores-0.1.3}/tests/test_indexes/test_local_index.py +0 -0
  51. {stores-0.1.1 → stores-0.1.3}/tests/test_indexes/test_venv_utils.py +0 -0
  52. {stores-0.1.1 → stores-0.1.3}/tests/test_parse/conftest.py +0 -0
  53. {stores-0.1.1 → stores-0.1.3}/tests/test_parse/test_parse.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: stores
3
- Version: 0.1.1
3
+ Version: 0.1.3
4
4
  Summary: Repository of Python functions and tools for LLMs
5
5
  License-File: LICENSE
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "stores"
3
- version = "0.1.1"
3
+ version = "0.1.3"
4
4
  description = "Repository of Python functions and tools for LLMs"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -0,0 +1,8 @@
1
+ import stores
2
+
3
+ # import stores.indexes.remote_index as remote
4
+
5
+ # remote.clear_cache()
6
+
7
+ index = stores.Index(["silanthro/slack"])
8
+ print(index.tools)
@@ -1,7 +1,7 @@
1
1
  import logging
2
2
  import os
3
3
  from pathlib import Path
4
- from typing import Callable
4
+ from typing import Callable, Optional
5
5
 
6
6
  from stores.indexes.base_index import BaseIndex
7
7
  from stores.indexes.local_index import LocalIndex
@@ -17,6 +17,8 @@ class Index(BaseIndex):
17
17
  self,
18
18
  tools: list[Callable, os.PathLike] | None = None,
19
19
  env_var: dict[str, dict] | None = None,
20
+ cache_dir: Optional[os.PathLike] = None,
21
+ reset_cache=False,
20
22
  ):
21
23
  self.env_var = env_var or {}
22
24
  tools = tools or []
@@ -38,7 +40,10 @@ class Index(BaseIndex):
38
40
  # Load RemoteIndex
39
41
  try:
40
42
  loaded_index = RemoteIndex(
41
- index_name, env_var=self.env_var.get(index_name)
43
+ index_name,
44
+ env_var=self.env_var.get(index_name),
45
+ cache_dir=cache_dir,
46
+ reset_cache=reset_cache,
42
47
  )
43
48
  except Exception:
44
49
  logger.warning(
@@ -1,7 +1,10 @@
1
1
  import json
2
2
  import logging
3
+ import shutil
3
4
  import venv
5
+ from os import PathLike
4
6
  from pathlib import Path
7
+ from typing import Optional
5
8
 
6
9
  import requests
7
10
  from git import Repo
@@ -21,6 +24,10 @@ INDEX_LOOKUP_URL = (
21
24
  )
22
25
 
23
26
 
27
+ def clear_default_cache():
28
+ shutil.rmtree(CACHE_DIR)
29
+
30
+
24
31
  def lookup_index(index_id: str, index_version: str | None = None):
25
32
  response = requests.post(
26
33
  INDEX_LOOKUP_URL,
@@ -39,11 +46,24 @@ def lookup_index(index_id: str, index_version: str | None = None):
39
46
 
40
47
 
41
48
  class RemoteIndex(BaseIndex):
42
- def __init__(self, index_id: str, env_var: dict | None = None):
49
+ def __init__(
50
+ self,
51
+ index_id: str,
52
+ env_var: dict | None = None,
53
+ cache_dir: Optional[PathLike] = None,
54
+ reset_cache=False,
55
+ ):
43
56
  self.index_id = index_id
44
- self.index_folder = CACHE_DIR / self.index_id
57
+ if cache_dir is None:
58
+ cache_dir = CACHE_DIR
59
+ else:
60
+ cache_dir = Path(cache_dir)
61
+ if reset_cache:
62
+ shutil.rmtree(cache_dir)
63
+ self.index_folder = cache_dir / self.index_id
45
64
  self.env_var = env_var or {}
46
65
  if not self.index_folder.exists():
66
+ logger.info(f"Installing {index_id}...")
47
67
  commit_like = None
48
68
  if ":" in index_id:
49
69
  index_id, commit_like = index_id.split(":")
@@ -93,6 +93,7 @@ def init_venv_tools(index_folder: os.PathLike, env_var: dict | None = None):
93
93
  tool_id=tool_id,
94
94
  index_folder=index_folder,
95
95
  venv=VENV_NAME,
96
+ env_var=env_var,
96
97
  )
97
98
  tool = parse_tool_signature(
98
99
  signature_dict=tool_sig,
@@ -105,9 +106,15 @@ def init_venv_tools(index_folder: os.PathLike, env_var: dict | None = None):
105
106
 
106
107
 
107
108
  # TODO: Sanitize tool_id, args, and kwargs
108
- def get_tool_signature(tool_id: str, index_folder: os.PathLike, venv: str = VENV_NAME):
109
+ def get_tool_signature(
110
+ tool_id: str,
111
+ index_folder: os.PathLike,
112
+ venv: str = VENV_NAME,
113
+ env_var: dict | None = None,
114
+ ):
109
115
  module_name = ".".join(tool_id.split(".")[:-1])
110
116
  tool_name = tool_id.split(".")[-1]
117
+ env_var = env_var or {}
111
118
 
112
119
  runner = f"""
113
120
  import pickle, sys, traceback, inspect, enum
@@ -115,44 +122,49 @@ from typing import Any, Dict, List, Literal, Tuple, Union, get_args, get_origin,
115
122
  import types as T
116
123
 
117
124
 
118
- def extract_type_info(typ):
125
+ def extract_type_info(typ, custom_types: list[str] | None = None):
126
+ custom_types = custom_types or []
127
+ if hasattr(typ, "__name__") and typ.__name__ in custom_types:
128
+ return typ.__name__
119
129
  origin = get_origin(typ)
120
130
  args = list(get_args(typ))
121
131
  if origin is Literal:
122
132
  return {{"type": "Literal", "values": args}}
123
133
  elif inspect.isclass(typ) and issubclass(typ, enum.Enum):
134
+ custom_types.append(typ.__name__)
124
135
  return {{
125
136
  "type": "Enum",
126
137
  "type_name": typ.__name__,
127
138
  "values": {{v.name: v.value for v in typ}},
128
139
  }}
129
140
  elif isinstance(typ, type) and typ.__class__.__name__ == "_TypedDictMeta":
141
+ custom_types.append(typ.__name__)
130
142
  hints = get_type_hints(typ)
131
143
  return {{
132
144
  "type": "TypedDict",
133
145
  "type_name": typ.__name__,
134
- "fields": {{k: extract_type_info(v) for k, v in hints.items()}}
146
+ "fields": {{k: extract_type_info(v, custom_types) for k, v in hints.items()}}
135
147
  }}
136
148
  elif origin in (list, List) or typ is list:
137
149
  return {{
138
150
  "type": "List",
139
- "item_type": extract_type_info(args[0]) if args else {{"type": Any}}
151
+ "item_type": extract_type_info(args[0], custom_types) if args else {{"type": Any}}
140
152
  }}
141
153
  elif origin in (dict, Dict) or typ is dict:
142
154
  return {{
143
155
  "type": "Dict",
144
- "key_type": extract_type_info(args[0]) if args else {{"type": Any}},
145
- "value_type": extract_type_info(args[1]) if len(args) > 1 else {{"type": Any}}
156
+ "key_type": extract_type_info(args[0], custom_types) if args else {{"type": Any}},
157
+ "value_type": extract_type_info(args[1], custom_types) if len(args) > 1 else {{"type": Any}}
146
158
  }}
147
159
  elif origin in (tuple, Tuple) or typ is tuple:
148
160
  return {{
149
161
  "type": "Tuple",
150
- "item_types": [extract_type_info(arg) for arg in args] if args else [{{"type": Any}}]
162
+ "item_types": [extract_type_info(arg, custom_types) for arg in args] if args else [{{"type": Any}}]
151
163
  }}
152
164
  elif origin is Union or origin is T.UnionType:
153
165
  return {{
154
166
  "type": "Union",
155
- "options": [extract_type_info(arg) for arg in args]
167
+ "options": [extract_type_info(arg, custom_types) for arg in args]
156
168
  }}
157
169
  else:
158
170
  return {{"type": typ}}
@@ -192,6 +204,7 @@ except Exception as e:
192
204
  [f"{venv}/bin/python", "-c", runner],
193
205
  capture_output=True,
194
206
  cwd=index_folder,
207
+ env=env_var,
195
208
  )
196
209
  try:
197
210
  response = pickle.loads(result.stdout)
@@ -205,33 +218,39 @@ except Exception as e:
205
218
  raise RuntimeError(f"Error loading tool {tool_id}:\n{response['error']}")
206
219
 
207
220
 
208
- def parse_param_type(param_info: dict):
221
+ def parse_param_type(param_info: dict, custom_types: list[str] | None = None):
222
+ custom_types = custom_types or []
223
+ # Support ForwardRef
209
224
  param_type = param_info["type"]
225
+ if param_type in custom_types:
226
+ return param_type
210
227
  if not isinstance(param_type, str):
211
228
  return param_type
212
229
  if param_type == "Literal":
213
230
  return Literal.__getitem__(tuple(param_info["values"]))
214
231
  elif param_type == "Enum":
232
+ custom_types.append(param_info["type_name"])
215
233
  return Enum(param_info["type_name"], param_info["values"])
216
234
  elif param_type == "TypedDict":
235
+ custom_types.append(param_info["type_name"])
217
236
  properties = {}
218
237
  for k, v in param_info["fields"].items():
219
- properties[k] = parse_param_type(v)
238
+ properties[k] = parse_param_type(v, custom_types)
220
239
  return TypedDict(param_info["type_name"], properties)
221
240
  elif param_type == "List":
222
- return list[parse_param_type(param_info["item_type"])]
241
+ return list[parse_param_type(param_info["item_type"], custom_types)]
223
242
  elif param_type == "Dict":
224
243
  return Dict[
225
- parse_param_type(param_info["key_type"]),
226
- parse_param_type(param_info["value_type"]),
244
+ parse_param_type(param_info["key_type"], custom_types),
245
+ parse_param_type(param_info["value_type"], custom_types),
227
246
  ]
228
247
  elif param_type == "Tuple":
229
248
  return Tuple.__getitem__(
230
- tuple([parse_param_type(i) for i in param_info["item_types"]])
249
+ tuple([parse_param_type(i, custom_types) for i in param_info["item_types"]])
231
250
  )
232
251
  elif param_type == "Union":
233
252
  return Union.__getitem__(
234
- tuple([parse_param_type(i) for i in param_info["options"]])
253
+ tuple([parse_param_type(i, custom_types) for i in param_info["options"]])
235
254
  )
236
255
  else:
237
256
  raise TypeError(f"Invalid param type {param_type} in param info {param_info}")
@@ -40,3 +40,12 @@ async def test_remote_index():
40
40
  )
41
41
  # Clean up index
42
42
  shutil.rmtree(stores.indexes.remote_index.CACHE_DIR / "silanthro/send-gmail:0.2.0")
43
+
44
+
45
+ async def test_remote_index_2():
46
+ # Check that env_vars are set correctly
47
+ stores.indexes.RemoteIndex(
48
+ "silanthro/filesystem:0.2.0",
49
+ env_var={"ALLOWED_DIR": "./test"},
50
+ )
51
+ shutil.rmtree(stores.indexes.remote_index.CACHE_DIR / "silanthro/filesystem:0.2.0")
@@ -2963,7 +2963,7 @@ wheels = [
2963
2963
 
2964
2964
  [[package]]
2965
2965
  name = "stores"
2966
- version = "0.1.0"
2966
+ version = "0.1.2"
2967
2967
  source = { editable = "." }
2968
2968
  dependencies = [
2969
2969
  { name = "dirtyjson" },
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