linkml-store 0.0.0__tar.gz → 0.1.7__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 (46) hide show
  1. {linkml_store-0.0.0 → linkml_store-0.1.7}/PKG-INFO +17 -6
  2. linkml_store-0.1.7/README.md +10 -0
  3. {linkml_store-0.0.0 → linkml_store-0.1.7}/pyproject.toml +14 -4
  4. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/__init__.py +2 -2
  5. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/client.py +113 -8
  6. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/collection.py +272 -34
  7. linkml_store-0.1.7/src/linkml_store/api/config.py +101 -0
  8. linkml_store-0.1.7/src/linkml_store/api/database.py +479 -0
  9. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/queries.py +12 -1
  10. linkml_store-0.1.7/src/linkml_store/api/stores/chromadb/__init__.py +3 -0
  11. linkml_store-0.1.7/src/linkml_store/api/stores/chromadb/chromadb_collection.py +121 -0
  12. linkml_store-0.1.7/src/linkml_store/api/stores/chromadb/chromadb_database.py +89 -0
  13. linkml_store-0.1.7/src/linkml_store/api/stores/duckdb/__init__.py +7 -0
  14. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/stores/duckdb/duckdb_collection.py +47 -14
  15. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/stores/duckdb/duckdb_database.py +38 -47
  16. linkml_store-0.1.7/src/linkml_store/api/stores/hdf5/hdf5_collection.py +104 -0
  17. linkml_store-0.1.7/src/linkml_store/api/stores/hdf5/hdf5_database.py +79 -0
  18. linkml_store-0.1.7/src/linkml_store/api/stores/mongodb/mongodb_collection.py +108 -0
  19. linkml_store-0.1.7/src/linkml_store/api/stores/mongodb/mongodb_database.py +103 -0
  20. linkml_store-0.1.7/src/linkml_store/api/stores/solr/__init__.py +3 -0
  21. linkml_store-0.1.7/src/linkml_store/api/stores/solr/solr_collection.py +133 -0
  22. linkml_store-0.1.7/src/linkml_store/api/stores/solr/solr_database.py +83 -0
  23. linkml_store-0.1.7/src/linkml_store/cli.py +369 -0
  24. linkml_store-0.1.7/src/linkml_store/index/__init__.py +33 -0
  25. linkml_store-0.0.0/src/linkml_store/index/implementations/llm_index.py → linkml_store-0.1.7/src/linkml_store/index/implementations/llm_indexer.py +2 -2
  26. linkml_store-0.0.0/src/linkml_store/index/implementations/simple_index.py → linkml_store-0.1.7/src/linkml_store/index/implementations/simple_indexer.py +6 -3
  27. linkml_store-0.0.0/src/linkml_store/index/index.py → linkml_store-0.1.7/src/linkml_store/index/indexer.py +7 -4
  28. linkml_store-0.1.7/src/linkml_store/utils/format_utils.py +93 -0
  29. linkml_store-0.1.7/src/linkml_store/utils/object_utils.py +81 -0
  30. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/utils/sql_utils.py +46 -7
  31. linkml_store-0.0.0/README.md +0 -7
  32. linkml_store-0.0.0/src/linkml_store/api/database.py +0 -215
  33. linkml_store-0.0.0/src/linkml_store/api/metadata.py +0 -5
  34. linkml_store-0.0.0/src/linkml_store/api/stores/mongodb/mongodb_collection.py +0 -56
  35. linkml_store-0.0.0/src/linkml_store/api/stores/mongodb/mongodb_database.py +0 -112
  36. {linkml_store-0.0.0 → linkml_store-0.1.7}/LICENSE +0 -0
  37. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/__init__.py +0 -0
  38. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/stores/__init__.py +0 -0
  39. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/stores/duckdb/mappings.py +0 -0
  40. {linkml_store-0.0.0/src/linkml_store/api/stores/duckdb → linkml_store-0.1.7/src/linkml_store/api/stores/hdf5}/__init__.py +0 -0
  41. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/api/stores/mongodb/__init__.py +0 -0
  42. /linkml_store-0.0.0/src/linkml_store/index/__init__.py → /linkml_store-0.1.7/src/linkml_store/api/stores/solr/solr_utils.py +0 -0
  43. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/constants.py +0 -0
  44. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/index/implementations/__init__.py +0 -0
  45. {linkml_store-0.0.0 → linkml_store-0.1.7}/src/linkml_store/utils/__init__.py +0 -0
  46. {linkml_store-0.0.0 → linkml_store-0.1.7}/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.7
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.7"
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"}
@@ -32,7 +36,9 @@ sphinx = {version = ">=6.1.3"}
32
36
  sphinx-rtd-theme = {version = ">=1.0.0"}
33
37
  sphinx-autodoc-typehints = {version = "<2.0.0"}
34
38
  sphinx-click = {version = ">=4.3.0"}
39
+ sphinx-automodapi = "*"
35
40
  myst-parser = {version = ">=0.18.1"}
41
+ furo = {version = "*"}
36
42
  nbsphinx = "*"
37
43
  jupyter = "*"
38
44
 
@@ -50,9 +56,13 @@ app = ["streamlit"]
50
56
  tests = ["black"]
51
57
  llm = ["llm"]
52
58
  mongodb = ["pymongo"]
59
+ chromadb = ["chromadb"]
60
+ h5py = ["h5py"]
61
+ validation = ["linkml"]
62
+ map = ["linkml_map"]
53
63
 
54
64
  [tool.poetry.scripts]
55
- linkml-store = "linkml_store.cli:main"
65
+ linkml-store = "linkml_store.cli:cli"
56
66
 
57
67
  [tool.poetry-dynamic-versioning]
58
68
  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,20 +1,31 @@
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
- A client provides access to named collections.
24
+ A client is the top-level object for interacting with databases.
25
+
26
+ A client has access to one or more :class:`Database` objects.
27
+
28
+ Each database consists of a number of :class:`.Collection` objects.
18
29
 
19
30
  Examples
20
31
  --------
@@ -22,7 +33,7 @@ class Client:
22
33
  >>> db = client.attach_database("duckdb", alias="test")
23
34
  >>> collection = db.create_collection("Person")
24
35
  >>> objs = [{"id": "P1", "name": "John", "age_in_years": 30}, {"id": "P2", "name": "Alice", "age_in_years": 25}]
25
- >>> collection.add(objs)
36
+ >>> collection.insert(objs)
26
37
  >>> qr = collection.find()
27
38
  >>> len(qr.rows)
28
39
  2
@@ -38,9 +49,76 @@ class Client:
38
49
 
39
50
  """
40
51
 
41
- handle: Optional[str] = None
52
+ metadata: Optional[ClientConfig] = None
42
53
  _databases: Optional[Dict[str, Database]] = None
43
54
 
55
+ def __init__(self, handle: Optional[str] = None, metadata: Optional[ClientConfig] = None):
56
+ """
57
+ Initialize a client.
58
+
59
+ :param handle:
60
+ :param metadata:
61
+ """
62
+ self.metadata = metadata
63
+ if not self.metadata:
64
+ self.metadata = ClientConfig()
65
+ self.metadata.handle = handle
66
+
67
+ @property
68
+ def handle(self) -> Optional[str]:
69
+ return self.metadata.handle
70
+
71
+ @property
72
+ def base_dir(self) -> Optional[str]:
73
+ """
74
+ Get the base directory for the client.
75
+
76
+ Wraps metadata.base_dir.
77
+
78
+ :return:
79
+ """
80
+ return self.metadata.base_dir
81
+
82
+ def from_config(self, config: Union[ClientConfig, str, Path], base_dir=None, **kwargs):
83
+ """
84
+ Create a client from a configuration.
85
+
86
+ Examples
87
+ --------
88
+ >>> from linkml_store.api.config import ClientConfig
89
+ >>> client = Client().from_config(ClientConfig(databases={"test": {"handle": "duckdb:///:memory:"}}))
90
+ >>> len(client.databases)
91
+ 1
92
+ >>> "test" in client.databases
93
+ True
94
+ >>> client.databases["test"].handle
95
+ 'duckdb:///:memory:'
96
+
97
+ :param config:
98
+ :param kwargs:
99
+ :return:
100
+
101
+ """
102
+ if isinstance(config, Path):
103
+ config = str(config)
104
+ if isinstance(config, str):
105
+ if not base_dir:
106
+ base_dir = Path(config).parent
107
+ parsed_obj = yaml.safe_load(open(config))
108
+ config = ClientConfig(**parsed_obj)
109
+ self.metadata = config
110
+ if base_dir:
111
+ self.metadata.base_dir = base_dir
112
+ self._initialize_databases(**kwargs)
113
+ return self
114
+
115
+ def _initialize_databases(self, **kwargs):
116
+ for name, db_config in self.metadata.databases.items():
117
+ handle = db_config.handle.format(base_dir=self.base_dir)
118
+ db_config.handle = handle
119
+ db = self.attach_database(handle, alias=name, **kwargs)
120
+ db.from_config(db_config)
121
+
44
122
  def attach_database(
45
123
  self,
46
124
  handle: str,
@@ -69,7 +147,6 @@ class Client:
69
147
  :param schema_view: schema view to associate with the database
70
148
  :param kwargs:
71
149
  :return:
72
-
73
150
  """
74
151
  if ":" not in handle:
75
152
  scheme = handle
@@ -87,6 +164,7 @@ class Client:
87
164
  if not self._databases:
88
165
  self._databases = {}
89
166
  self._databases[alias] = db
167
+ db.parent = self
90
168
  return db
91
169
 
92
170
  def get_database(self, name: Optional[str] = None, create_if_not_exists=True, **kwargs) -> Database:
@@ -101,7 +179,7 @@ class Client:
101
179
  >>> db == retrieved_db
102
180
  True
103
181
 
104
- :param name:
182
+ :param name: if None, there must be a single database attached
105
183
  :param create_if_not_exists:
106
184
  :param kwargs:
107
185
  :return:
@@ -149,3 +227,30 @@ class Client:
149
227
  if not self._databases:
150
228
  self._databases = {}
151
229
  return self._databases
230
+
231
+ def drop_database(self, name: str, missing_ok=False, **kwargs):
232
+ """
233
+ Drop a database.
234
+
235
+ :param name:
236
+ :param missing_ok:
237
+ :return:
238
+ """
239
+ if name in self._databases:
240
+ db = self._databases[name]
241
+ db.drop(**kwargs)
242
+ del self._databases[name]
243
+ else:
244
+ if not missing_ok:
245
+ raise ValueError(f"Database {name} not found")
246
+
247
+ def drop_all_databases(self, **kwargs):
248
+ """
249
+ Drop all databases.
250
+
251
+ :param missing_ok:
252
+ :return:
253
+ """
254
+ for name in list(self._databases.keys()):
255
+ self.drop_database(name, missing_ok=False, **kwargs)
256
+ self._databases = {}