linkml-store 0.0.0__tar.gz → 0.1.6__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.

Potentially problematic release.


This version of linkml-store might be problematic. Click here for more details.

Files changed (45) hide show
  1. {linkml_store-0.0.0 → linkml_store-0.1.6}/PKG-INFO +17 -6
  2. linkml_store-0.1.6/README.md +10 -0
  3. {linkml_store-0.0.0 → linkml_store-0.1.6}/pyproject.toml +13 -4
  4. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/__init__.py +2 -2
  5. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/client.py +108 -7
  6. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/collection.py +221 -30
  7. linkml_store-0.1.6/src/linkml_store/api/config.py +97 -0
  8. linkml_store-0.1.6/src/linkml_store/api/database.py +405 -0
  9. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/queries.py +12 -1
  10. linkml_store-0.1.6/src/linkml_store/api/stores/chromadb/chromadb_collection.py +114 -0
  11. linkml_store-0.1.6/src/linkml_store/api/stores/chromadb/chromadb_database.py +89 -0
  12. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/stores/duckdb/duckdb_collection.py +47 -14
  13. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/stores/duckdb/duckdb_database.py +35 -44
  14. linkml_store-0.1.6/src/linkml_store/api/stores/hdf5/hdf5_collection.py +104 -0
  15. linkml_store-0.1.6/src/linkml_store/api/stores/hdf5/hdf5_database.py +79 -0
  16. linkml_store-0.1.6/src/linkml_store/api/stores/mongodb/mongodb_collection.py +102 -0
  17. linkml_store-0.1.6/src/linkml_store/api/stores/mongodb/mongodb_database.py +103 -0
  18. linkml_store-0.1.6/src/linkml_store/api/stores/solr/solr_collection.py +132 -0
  19. linkml_store-0.1.6/src/linkml_store/api/stores/solr/solr_database.py +82 -0
  20. linkml_store-0.1.6/src/linkml_store/cli.py +369 -0
  21. linkml_store-0.1.6/src/linkml_store/index/__init__.py +33 -0
  22. linkml_store-0.1.6/src/linkml_store/index/implementations/__init__.py +0 -0
  23. linkml_store-0.0.0/src/linkml_store/index/implementations/llm_index.py → linkml_store-0.1.6/src/linkml_store/index/implementations/llm_indexer.py +2 -2
  24. linkml_store-0.0.0/src/linkml_store/index/implementations/simple_index.py → linkml_store-0.1.6/src/linkml_store/index/implementations/simple_indexer.py +6 -3
  25. linkml_store-0.0.0/src/linkml_store/index/index.py → linkml_store-0.1.6/src/linkml_store/index/indexer.py +7 -4
  26. linkml_store-0.1.6/src/linkml_store/utils/__init__.py +0 -0
  27. linkml_store-0.1.6/src/linkml_store/utils/format_utils.py +93 -0
  28. linkml_store-0.1.6/src/linkml_store/utils/object_utils.py +73 -0
  29. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/utils/sql_utils.py +46 -7
  30. linkml_store-0.0.0/README.md +0 -7
  31. linkml_store-0.0.0/src/linkml_store/api/database.py +0 -215
  32. linkml_store-0.0.0/src/linkml_store/api/metadata.py +0 -5
  33. linkml_store-0.0.0/src/linkml_store/api/stores/mongodb/mongodb_collection.py +0 -56
  34. linkml_store-0.0.0/src/linkml_store/api/stores/mongodb/mongodb_database.py +0 -112
  35. {linkml_store-0.0.0 → linkml_store-0.1.6}/LICENSE +0 -0
  36. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/__init__.py +0 -0
  37. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/stores/__init__.py +0 -0
  38. {linkml_store-0.0.0/src/linkml_store/api/stores/duckdb → linkml_store-0.1.6/src/linkml_store/api/stores/chromadb}/__init__.py +0 -0
  39. {linkml_store-0.0.0/src/linkml_store/api/stores/mongodb → linkml_store-0.1.6/src/linkml_store/api/stores/duckdb}/__init__.py +0 -0
  40. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/api/stores/duckdb/mappings.py +0 -0
  41. {linkml_store-0.0.0/src/linkml_store/index → linkml_store-0.1.6/src/linkml_store/api/stores/hdf5}/__init__.py +0 -0
  42. {linkml_store-0.0.0/src/linkml_store/index/implementations → linkml_store-0.1.6/src/linkml_store/api/stores/mongodb}/__init__.py +0 -0
  43. /linkml_store-0.0.0/src/linkml_store/utils/__init__.py → /linkml_store-0.1.6/src/linkml_store/api/stores/solr/solr_utils.py +0 -0
  44. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/constants.py +0 -0
  45. {linkml_store-0.0.0 → linkml_store-0.1.6}/src/linkml_store/utils/io.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: linkml-store
3
- Version: 0.0.0
3
+ Version: 0.1.6
4
4
  Summary: linkml-store
5
5
  License: MIT
6
6
  Author: Author 1
@@ -14,17 +14,25 @@ Classifier: Programming Language :: Python :: 3.11
14
14
  Classifier: Programming Language :: Python :: 3.12
15
15
  Provides-Extra: analytics
16
16
  Provides-Extra: app
17
+ Provides-Extra: chromadb
18
+ Provides-Extra: h5py
17
19
  Provides-Extra: llm
20
+ Provides-Extra: map
18
21
  Provides-Extra: mongodb
19
22
  Provides-Extra: tests
23
+ Provides-Extra: validation
20
24
  Requires-Dist: black (>=24.0.0) ; extra == "tests"
25
+ Requires-Dist: chromadb ; extra == "chromadb"
21
26
  Requires-Dist: click
22
27
  Requires-Dist: duckdb (>=0.10.1,<0.11.0)
23
- Requires-Dist: duckdb-engine (>=0.11.2,<0.12.0)
28
+ Requires-Dist: duckdb-engine (>=0.11.2)
29
+ Requires-Dist: h5py ; extra == "h5py"
30
+ Requires-Dist: linkml ; extra == "validation"
24
31
  Requires-Dist: linkml-runtime (>=1.7.5,<2.0.0)
32
+ Requires-Dist: linkml_map ; extra == "map"
25
33
  Requires-Dist: llm ; extra == "llm"
26
34
  Requires-Dist: matplotlib ; extra == "analytics"
27
- Requires-Dist: pandas (>=2.2.1,<3.0.0) ; extra == "analytics"
35
+ Requires-Dist: pandas (>=2.2.1) ; extra == "analytics"
28
36
  Requires-Dist: plotly ; extra == "analytics"
29
37
  Requires-Dist: pydantic (>=2.0.0,<3.0.0)
30
38
  Requires-Dist: pymongo ; extra == "mongodb"
@@ -36,9 +44,12 @@ Description-Content-Type: text/markdown
36
44
 
37
45
  # linkml-store
38
46
 
39
- This is the project description.
47
+ An integration layer for multiple database backends
40
48
 
41
- # Acknowledgements
49
+ Currently this software is alpha, and has only been tested with DuckDB backends. See the Tutorial for more information.
42
50
 
43
- This [cookiecutter](https://cookiecutter.readthedocs.io/en/stable/README.html) project was developed from the [monarch-project-template](https://github.com/monarch-initiative/monarch-project-template) template and will be kept up-to-date using [cruft](https://cruft.github.io/cruft/).
51
+ There is also experimental support for vector-based indexing using OpenAI test embedding via the `llm` library.
52
+
53
+ The goals of this project are to provide high level access to data stored in heterogeneous databases,
54
+ with optional schema management using LinkML.
44
55
 
@@ -0,0 +1,10 @@
1
+ # linkml-store
2
+
3
+ An integration layer for multiple database backends
4
+
5
+ Currently this software is alpha, and has only been tested with DuckDB backends. See the Tutorial for more information.
6
+
7
+ There is also experimental support for vector-based indexing using OpenAI test embedding via the `llm` library.
8
+
9
+ The goals of this project are to provide high level access to data stored in heterogeneous databases,
10
+ with optional schema management using LinkML.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "linkml-store"
3
- version = "0.0.0"
3
+ version = "0.1.6"
4
4
  description = "linkml-store"
5
5
  authors = ["Author 1 <author@org.org>"]
6
6
  license = "MIT"
@@ -14,7 +14,7 @@ linkml-runtime = "^1.7.5"
14
14
  streamlit = { version = "^1.32.2", optional = true }
15
15
  sqlalchemy = "*"
16
16
  duckdb = "^0.10.1"
17
- duckdb-engine = "^0.11.2"
17
+ duckdb-engine = ">=0.11.2"
18
18
  matplotlib = { version = "*", optional = true }
19
19
  seaborn = { version = "*", optional = true }
20
20
  plotly = { version = "*", optional = true }
@@ -22,7 +22,11 @@ pystow = "^0.5.4"
22
22
  black = { version=">=24.0.0", optional = true }
23
23
  llm = { version="*", optional = true }
24
24
  pymongo = { version="*", optional = true }
25
- pandas = "^2.2.1"
25
+ chromadb = { version="*", optional = true }
26
+ h5py = { version="*", optional = true }
27
+ linkml = { version="*", optional = true }
28
+ linkml_map = { version="*", optional = true }
29
+ pandas = ">=2.2.1"
26
30
 
27
31
  [tool.poetry.group.dev.dependencies]
28
32
  pytest = {version = ">=7.1.2"}
@@ -33,6 +37,7 @@ sphinx-rtd-theme = {version = ">=1.0.0"}
33
37
  sphinx-autodoc-typehints = {version = "<2.0.0"}
34
38
  sphinx-click = {version = ">=4.3.0"}
35
39
  myst-parser = {version = ">=0.18.1"}
40
+ furo = {version = "*"}
36
41
  nbsphinx = "*"
37
42
  jupyter = "*"
38
43
 
@@ -50,9 +55,13 @@ app = ["streamlit"]
50
55
  tests = ["black"]
51
56
  llm = ["llm"]
52
57
  mongodb = ["pymongo"]
58
+ chromadb = ["chromadb"]
59
+ h5py = ["h5py"]
60
+ validation = ["linkml"]
61
+ map = ["linkml_map"]
53
62
 
54
63
  [tool.poetry.scripts]
55
- linkml-store = "linkml_store.cli:main"
64
+ linkml-store = "linkml_store.cli:cli"
56
65
 
57
66
  [tool.poetry-dynamic-versioning]
58
67
  enable = false
@@ -1,8 +1,8 @@
1
1
  # flake8: noqa: E402
2
2
  from linkml_store.api.collection import Collection
3
3
  from linkml_store.api.database import Database
4
- from linkml_store.api.metadata import MetaData
5
4
  from linkml_store.api.client import Client
5
+
6
6
  # flake8: noqa
7
7
 
8
- __all__ = ["Client", "Database", "MetaData", "Collection"]
8
+ __all__ = ["Client", "Database", "Collection"]
@@ -1,17 +1,24 @@
1
- from dataclasses import dataclass
2
- from typing import Dict, Optional
1
+ from pathlib import Path
2
+ from typing import Dict, Optional, Union
3
3
 
4
+ import yaml
4
5
  from linkml_runtime import SchemaView
5
6
 
6
7
  from linkml_store.api import Database
8
+ from linkml_store.api.config import ClientConfig
9
+ from linkml_store.api.stores.chromadb.chromadb_database import ChromaDBDatabase
7
10
  from linkml_store.api.stores.duckdb.duckdb_database import DuckDBDatabase
11
+ from linkml_store.api.stores.mongodb.mongodb_database import MongoDBDatabase
12
+ from linkml_store.api.stores.solr.solr_database import SolrDatabase
8
13
 
9
14
  HANDLE_MAP = {
10
15
  "duckdb": DuckDBDatabase,
16
+ "solr": SolrDatabase,
17
+ "mongodb": MongoDBDatabase,
18
+ "chromadb": ChromaDBDatabase,
11
19
  }
12
20
 
13
21
 
14
- @dataclass
15
22
  class Client:
16
23
  """
17
24
  A client provides access to named collections.
@@ -22,7 +29,7 @@ class Client:
22
29
  >>> db = client.attach_database("duckdb", alias="test")
23
30
  >>> collection = db.create_collection("Person")
24
31
  >>> objs = [{"id": "P1", "name": "John", "age_in_years": 30}, {"id": "P2", "name": "Alice", "age_in_years": 25}]
25
- >>> collection.add(objs)
32
+ >>> collection.insert(objs)
26
33
  >>> qr = collection.find()
27
34
  >>> len(qr.rows)
28
35
  2
@@ -38,9 +45,76 @@ class Client:
38
45
 
39
46
  """
40
47
 
41
- handle: Optional[str] = None
48
+ metadata: Optional[ClientConfig] = None
42
49
  _databases: Optional[Dict[str, Database]] = None
43
50
 
51
+ def __init__(self, handle: Optional[str] = None, metadata: Optional[ClientConfig] = None):
52
+ """
53
+ Initialize a client.
54
+
55
+ :param handle:
56
+ :param metadata:
57
+ """
58
+ self.metadata = metadata
59
+ if not self.metadata:
60
+ self.metadata = ClientConfig()
61
+ self.metadata.handle = handle
62
+
63
+ @property
64
+ def handle(self) -> Optional[str]:
65
+ return self.metadata.handle
66
+
67
+ @property
68
+ def base_dir(self) -> Optional[str]:
69
+ """
70
+ Get the base directory for the client.
71
+
72
+ Wraps metadata.base_dir.
73
+
74
+ :return:
75
+ """
76
+ return self.metadata.base_dir
77
+
78
+ def from_config(self, config: Union[ClientConfig, str, Path], base_dir=None, **kwargs):
79
+ """
80
+ Create a client from a configuration.
81
+
82
+ Examples
83
+ --------
84
+ >>> from linkml_store.api.config import ClientConfig
85
+ >>> client = Client().from_config(ClientConfig(databases={"test": {"handle": "duckdb:///:memory:"}}))
86
+ >>> len(client.databases)
87
+ 1
88
+ >>> "test" in client.databases
89
+ True
90
+ >>> client.databases["test"].handle
91
+ 'duckdb:///:memory:'
92
+
93
+ :param config:
94
+ :param kwargs:
95
+ :return:
96
+
97
+ """
98
+ if isinstance(config, Path):
99
+ config = str(config)
100
+ if isinstance(config, str):
101
+ if not base_dir:
102
+ base_dir = Path(config).parent
103
+ parsed_obj = yaml.safe_load(open(config))
104
+ config = ClientConfig(**parsed_obj)
105
+ self.metadata = config
106
+ if base_dir:
107
+ self.metadata.base_dir = base_dir
108
+ self._initialize_databases(**kwargs)
109
+ return self
110
+
111
+ def _initialize_databases(self, **kwargs):
112
+ for name, db_config in self.metadata.databases.items():
113
+ handle = db_config.handle.format(base_dir=self.base_dir)
114
+ db_config.handle = handle
115
+ db = self.attach_database(handle, alias=name, **kwargs)
116
+ db.from_config(db_config)
117
+
44
118
  def attach_database(
45
119
  self,
46
120
  handle: str,
@@ -69,7 +143,6 @@ class Client:
69
143
  :param schema_view: schema view to associate with the database
70
144
  :param kwargs:
71
145
  :return:
72
-
73
146
  """
74
147
  if ":" not in handle:
75
148
  scheme = handle
@@ -87,6 +160,7 @@ class Client:
87
160
  if not self._databases:
88
161
  self._databases = {}
89
162
  self._databases[alias] = db
163
+ db.parent = self
90
164
  return db
91
165
 
92
166
  def get_database(self, name: Optional[str] = None, create_if_not_exists=True, **kwargs) -> Database:
@@ -101,7 +175,7 @@ class Client:
101
175
  >>> db == retrieved_db
102
176
  True
103
177
 
104
- :param name:
178
+ :param name: if None, there must be a single database attached
105
179
  :param create_if_not_exists:
106
180
  :param kwargs:
107
181
  :return:
@@ -149,3 +223,30 @@ class Client:
149
223
  if not self._databases:
150
224
  self._databases = {}
151
225
  return self._databases
226
+
227
+ def drop_database(self, name: str, missing_ok=False, **kwargs):
228
+ """
229
+ Drop a database.
230
+
231
+ :param name:
232
+ :param missing_ok:
233
+ :return:
234
+ """
235
+ if name in self._databases:
236
+ db = self._databases[name]
237
+ db.drop(**kwargs)
238
+ del self._databases[name]
239
+ else:
240
+ if not missing_ok:
241
+ raise ValueError(f"Database {name} not found")
242
+
243
+ def drop_all_databases(self, **kwargs):
244
+ """
245
+ Drop all databases.
246
+
247
+ :param missing_ok:
248
+ :return:
249
+ """
250
+ for name in list(self._databases.keys()):
251
+ self.drop_database(name, missing_ok=False, **kwargs)
252
+ self._databases = {}