json-database 0.10.2a1__tar.gz → 1.0.2a1__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.
- {json_database-0.10.2a1 → json_database-1.0.2a1}/PKG-INFO +13 -13
- {json_database-0.10.2a1 → json_database-1.0.2a1}/README.md +11 -10
- json_database-1.0.2a1/json_database/version.py +8 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database.egg-info/PKG-INFO +13 -13
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database.egg-info/SOURCES.txt +0 -3
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database.egg-info/requires.txt +1 -2
- {json_database-0.10.2a1 → json_database-1.0.2a1}/pyproject.toml +14 -6
- json_database-0.10.2a1/json_database/hpm.py +0 -105
- json_database-0.10.2a1/json_database/version.py +0 -6
- json_database-0.10.2a1/json_database.egg-info/entry_points.txt +0 -2
- json_database-0.10.2a1/test/test_hpm.py +0 -176
- {json_database-0.10.2a1 → json_database-1.0.2a1}/LICENSE +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database/__init__.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database/crypto.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database/exceptions.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database/search.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database/utils.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database/xdg_utils.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database.egg-info/dependency_links.txt +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/json_database.egg-info/top_level.txt +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/setup.cfg +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_crypto.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_database.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_e2e_user_database.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_encrypted_storage.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_exceptions.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_query.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_search.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_storage.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_xdg.py +0 -0
- {json_database-0.10.2a1 → json_database-1.0.2a1}/test/test_xdg_utils.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: json_database
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.2a1
|
|
4
4
|
Summary: searchable json database with persistence
|
|
5
5
|
Author-email: jarbasAI <jarbasai@mailfence.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Requires-Dist: combo_lock<1.0.0,>=0.2.1
|
|
|
12
12
|
Provides-Extra: crypto
|
|
13
13
|
Requires-Dist: pycryptodomex; extra == "crypto"
|
|
14
14
|
Provides-Extra: hpm
|
|
15
|
-
Requires-Dist: hivemind-plugin
|
|
15
|
+
Requires-Dist: hivemind-json-db-plugin>=0.0.3a2; extra == "hpm"
|
|
16
16
|
Provides-Extra: test
|
|
17
17
|
Requires-Dist: coveralls>=1.8.2; extra == "test"
|
|
18
18
|
Requires-Dist: flake8>=3.7.9; extra == "test"
|
|
@@ -20,7 +20,6 @@ Requires-Dist: pytest>=5.2.4; extra == "test"
|
|
|
20
20
|
Requires-Dist: pytest-cov>=2.8.1; extra == "test"
|
|
21
21
|
Requires-Dist: cov-core>=1.15.0; extra == "test"
|
|
22
22
|
Requires-Dist: pycryptodomex; extra == "test"
|
|
23
|
-
Requires-Dist: hivemind-plugin-manager<1.0.0,>=0.5.0; extra == "test"
|
|
24
23
|
Dynamic: license-file
|
|
25
24
|
|
|
26
25
|
# json_database
|
|
@@ -80,7 +79,6 @@ results = Query(db).equal("role", "user").build()
|
|
|
80
79
|
- File locking via `combo_lock` for safe concurrent access
|
|
81
80
|
- Supports commented JSON files (`//` and `#` line comments)
|
|
82
81
|
- Arbitrary Python objects stored via automatic `jsonify_recursively` conversion
|
|
83
|
-
- HiveMind plugin (`hivemind-json-db-plugin`) for voice assistant integration
|
|
84
82
|
|
|
85
83
|
## Configuration / Key Options
|
|
86
84
|
|
|
@@ -116,15 +114,17 @@ results = Query(db).equal("role", "user").build()
|
|
|
116
114
|
|
|
117
115
|
## HiveMind Integration
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
The HiveMind database-plugin adapter that used to ship as
|
|
118
|
+
`json_database.hpm:JsonDB` has been extracted into its own package,
|
|
119
|
+
[`hivemind-json-db-plugin`](https://github.com/JarbasHiveMind/hivemind-json-db-plugin),
|
|
120
|
+
so it can release on a HiveMind-aligned cadence and `json_database` doesn't pull
|
|
121
|
+
in `hivemind-plugin-manager` for users who don't need it.
|
|
122
|
+
|
|
123
|
+
For the 1.x line, `pip install json_database[hpm]` continues to work — it now
|
|
124
|
+
transitively installs `hivemind-json-db-plugin` so the `hivemind.database`
|
|
125
|
+
entry point remains available without code changes. **The `[hpm]` extra will
|
|
126
|
+
be removed in 2.0.0;** users should migrate to
|
|
127
|
+
`pip install hivemind-json-db-plugin` directly.
|
|
128
128
|
|
|
129
129
|
## License
|
|
130
130
|
|
|
@@ -55,7 +55,6 @@ results = Query(db).equal("role", "user").build()
|
|
|
55
55
|
- File locking via `combo_lock` for safe concurrent access
|
|
56
56
|
- Supports commented JSON files (`//` and `#` line comments)
|
|
57
57
|
- Arbitrary Python objects stored via automatic `jsonify_recursively` conversion
|
|
58
|
-
- HiveMind plugin (`hivemind-json-db-plugin`) for voice assistant integration
|
|
59
58
|
|
|
60
59
|
## Configuration / Key Options
|
|
61
60
|
|
|
@@ -91,15 +90,17 @@ results = Query(db).equal("role", "user").build()
|
|
|
91
90
|
|
|
92
91
|
## HiveMind Integration
|
|
93
92
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
93
|
+
The HiveMind database-plugin adapter that used to ship as
|
|
94
|
+
`json_database.hpm:JsonDB` has been extracted into its own package,
|
|
95
|
+
[`hivemind-json-db-plugin`](https://github.com/JarbasHiveMind/hivemind-json-db-plugin),
|
|
96
|
+
so it can release on a HiveMind-aligned cadence and `json_database` doesn't pull
|
|
97
|
+
in `hivemind-plugin-manager` for users who don't need it.
|
|
98
|
+
|
|
99
|
+
For the 1.x line, `pip install json_database[hpm]` continues to work — it now
|
|
100
|
+
transitively installs `hivemind-json-db-plugin` so the `hivemind.database`
|
|
101
|
+
entry point remains available without code changes. **The `[hpm]` extra will
|
|
102
|
+
be removed in 2.0.0;** users should migrate to
|
|
103
|
+
`pip install hivemind-json-db-plugin` directly.
|
|
103
104
|
|
|
104
105
|
## License
|
|
105
106
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: json_database
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 1.0.2a1
|
|
4
4
|
Summary: searchable json database with persistence
|
|
5
5
|
Author-email: jarbasAI <jarbasai@mailfence.com>
|
|
6
6
|
License: MIT
|
|
@@ -12,7 +12,7 @@ Requires-Dist: combo_lock<1.0.0,>=0.2.1
|
|
|
12
12
|
Provides-Extra: crypto
|
|
13
13
|
Requires-Dist: pycryptodomex; extra == "crypto"
|
|
14
14
|
Provides-Extra: hpm
|
|
15
|
-
Requires-Dist: hivemind-plugin
|
|
15
|
+
Requires-Dist: hivemind-json-db-plugin>=0.0.3a2; extra == "hpm"
|
|
16
16
|
Provides-Extra: test
|
|
17
17
|
Requires-Dist: coveralls>=1.8.2; extra == "test"
|
|
18
18
|
Requires-Dist: flake8>=3.7.9; extra == "test"
|
|
@@ -20,7 +20,6 @@ Requires-Dist: pytest>=5.2.4; extra == "test"
|
|
|
20
20
|
Requires-Dist: pytest-cov>=2.8.1; extra == "test"
|
|
21
21
|
Requires-Dist: cov-core>=1.15.0; extra == "test"
|
|
22
22
|
Requires-Dist: pycryptodomex; extra == "test"
|
|
23
|
-
Requires-Dist: hivemind-plugin-manager<1.0.0,>=0.5.0; extra == "test"
|
|
24
23
|
Dynamic: license-file
|
|
25
24
|
|
|
26
25
|
# json_database
|
|
@@ -80,7 +79,6 @@ results = Query(db).equal("role", "user").build()
|
|
|
80
79
|
- File locking via `combo_lock` for safe concurrent access
|
|
81
80
|
- Supports commented JSON files (`//` and `#` line comments)
|
|
82
81
|
- Arbitrary Python objects stored via automatic `jsonify_recursively` conversion
|
|
83
|
-
- HiveMind plugin (`hivemind-json-db-plugin`) for voice assistant integration
|
|
84
82
|
|
|
85
83
|
## Configuration / Key Options
|
|
86
84
|
|
|
@@ -116,15 +114,17 @@ results = Query(db).equal("role", "user").build()
|
|
|
116
114
|
|
|
117
115
|
## HiveMind Integration
|
|
118
116
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
117
|
+
The HiveMind database-plugin adapter that used to ship as
|
|
118
|
+
`json_database.hpm:JsonDB` has been extracted into its own package,
|
|
119
|
+
[`hivemind-json-db-plugin`](https://github.com/JarbasHiveMind/hivemind-json-db-plugin),
|
|
120
|
+
so it can release on a HiveMind-aligned cadence and `json_database` doesn't pull
|
|
121
|
+
in `hivemind-plugin-manager` for users who don't need it.
|
|
122
|
+
|
|
123
|
+
For the 1.x line, `pip install json_database[hpm]` continues to work — it now
|
|
124
|
+
transitively installs `hivemind-json-db-plugin` so the `hivemind.database`
|
|
125
|
+
entry point remains available without code changes. **The `[hpm]` extra will
|
|
126
|
+
be removed in 2.0.0;** users should migrate to
|
|
127
|
+
`pip install hivemind-json-db-plugin` directly.
|
|
128
128
|
|
|
129
129
|
## License
|
|
130
130
|
|
|
@@ -4,7 +4,6 @@ pyproject.toml
|
|
|
4
4
|
json_database/__init__.py
|
|
5
5
|
json_database/crypto.py
|
|
6
6
|
json_database/exceptions.py
|
|
7
|
-
json_database/hpm.py
|
|
8
7
|
json_database/search.py
|
|
9
8
|
json_database/utils.py
|
|
10
9
|
json_database/version.py
|
|
@@ -12,7 +11,6 @@ json_database/xdg_utils.py
|
|
|
12
11
|
json_database.egg-info/PKG-INFO
|
|
13
12
|
json_database.egg-info/SOURCES.txt
|
|
14
13
|
json_database.egg-info/dependency_links.txt
|
|
15
|
-
json_database.egg-info/entry_points.txt
|
|
16
14
|
json_database.egg-info/requires.txt
|
|
17
15
|
json_database.egg-info/top_level.txt
|
|
18
16
|
test/test_crypto.py
|
|
@@ -20,7 +18,6 @@ test/test_database.py
|
|
|
20
18
|
test/test_e2e_user_database.py
|
|
21
19
|
test/test_encrypted_storage.py
|
|
22
20
|
test/test_exceptions.py
|
|
23
|
-
test/test_hpm.py
|
|
24
21
|
test/test_query.py
|
|
25
22
|
test/test_search.py
|
|
26
23
|
test/test_storage.py
|
|
@@ -4,7 +4,7 @@ combo_lock<1.0.0,>=0.2.1
|
|
|
4
4
|
pycryptodomex
|
|
5
5
|
|
|
6
6
|
[hpm]
|
|
7
|
-
hivemind-plugin
|
|
7
|
+
hivemind-json-db-plugin>=0.0.3a2
|
|
8
8
|
|
|
9
9
|
[test]
|
|
10
10
|
coveralls>=1.8.2
|
|
@@ -13,4 +13,3 @@ pytest>=5.2.4
|
|
|
13
13
|
pytest-cov>=2.8.1
|
|
14
14
|
cov-core>=1.15.0
|
|
15
15
|
pycryptodomex
|
|
16
|
-
hivemind-plugin-manager<1.0.0,>=0.5.0
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
[build-system]
|
|
2
|
-
requires = ["setuptools>=
|
|
2
|
+
requires = ["setuptools>=61", "wheel"]
|
|
3
3
|
build-backend = "setuptools.build_meta"
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "json_database"
|
|
7
|
-
|
|
7
|
+
dynamic = ["version"]
|
|
8
8
|
description = "searchable json database with persistence"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -16,7 +16,16 @@ dependencies = [
|
|
|
16
16
|
|
|
17
17
|
[project.optional-dependencies]
|
|
18
18
|
crypto = ["pycryptodomex"]
|
|
19
|
-
|
|
19
|
+
# Back-compat shim for the 1.x line — ``json_database[hpm]`` keeps
|
|
20
|
+
# resolving to a working install of the HiveMind database plugin so
|
|
21
|
+
# existing ``pip install json_database[hpm]`` users don't break on
|
|
22
|
+
# upgrade. The adapter itself was extracted into
|
|
23
|
+
# https://github.com/JarbasHiveMind/hivemind-json-db-plugin; this
|
|
24
|
+
# extra simply pulls it in transitively so the
|
|
25
|
+
# ``hivemind-json-db-plugin`` entry point remains available.
|
|
26
|
+
# This extra will be REMOVED in 2.0.0 — migrate to
|
|
27
|
+
# ``pip install hivemind-json-db-plugin`` directly.
|
|
28
|
+
hpm = ["hivemind-json-db-plugin>=0.0.3a2"]
|
|
20
29
|
test = [
|
|
21
30
|
"coveralls>=1.8.2",
|
|
22
31
|
"flake8>=3.7.9",
|
|
@@ -24,14 +33,13 @@ test = [
|
|
|
24
33
|
"pytest-cov>=2.8.1",
|
|
25
34
|
"cov-core>=1.15.0",
|
|
26
35
|
"pycryptodomex",
|
|
27
|
-
"hivemind-plugin-manager>=0.5.0,<1.0.0",
|
|
28
36
|
]
|
|
29
37
|
|
|
30
38
|
[project.urls]
|
|
31
39
|
Homepage = "https://github.com/TigreGotico/json_database"
|
|
32
40
|
|
|
33
|
-
[
|
|
34
|
-
|
|
41
|
+
[tool.setuptools.dynamic]
|
|
42
|
+
version = {attr = "json_database.version.__version__"}
|
|
35
43
|
|
|
36
44
|
[tool.setuptools.packages.find]
|
|
37
45
|
where = ["."]
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import copy
|
|
2
|
-
from hivemind_plugin_manager.database import Client, AbstractDB, cast2client
|
|
3
|
-
from ovos_utils.log import LOG
|
|
4
|
-
from ovos_utils.xdg_utils import xdg_data_home
|
|
5
|
-
from typing import Union, Iterable, List, Optional
|
|
6
|
-
from json_database import JsonStorageXDG, EncryptedJsonStorageXDG
|
|
7
|
-
from dataclasses import dataclass
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
@dataclass
|
|
11
|
-
class JsonDB(AbstractDB):
|
|
12
|
-
"""HiveMind Database implementation using JSON files."""
|
|
13
|
-
name: str = "clients"
|
|
14
|
-
subfolder: str = "hivemind-core"
|
|
15
|
-
password: Optional[str] = None
|
|
16
|
-
|
|
17
|
-
def __post_init__(self):
|
|
18
|
-
if self.password:
|
|
19
|
-
self._db = EncryptedJsonStorageXDG(encrypt_key=self.password,
|
|
20
|
-
name=self.name,
|
|
21
|
-
subfolder=self.subfolder,
|
|
22
|
-
xdg_folder=xdg_data_home())
|
|
23
|
-
else:
|
|
24
|
-
self._db = JsonStorageXDG(self.name,
|
|
25
|
-
subfolder=self.subfolder,
|
|
26
|
-
xdg_folder=xdg_data_home())
|
|
27
|
-
LOG.debug(f"json database path: {self._db.path}")
|
|
28
|
-
|
|
29
|
-
def sync(self):
|
|
30
|
-
"""update db from disk if needed"""
|
|
31
|
-
self._db.reload()
|
|
32
|
-
|
|
33
|
-
def add_item(self, client: Client) -> bool:
|
|
34
|
-
"""
|
|
35
|
-
Add a client to the JSON database.
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
client: The client to be added.
|
|
39
|
-
|
|
40
|
-
Returns:
|
|
41
|
-
True if the addition was successful, False otherwise.
|
|
42
|
-
"""
|
|
43
|
-
# Deep copy to break aliasing: dict(client.__dict__) is shallow, so
|
|
44
|
-
# mutable fields (metadata dict, intent/skill/message/allowed lists)
|
|
45
|
-
# would otherwise reference caller state and pick up later mutations
|
|
46
|
-
# on the next commit. Snapshot once on insert.
|
|
47
|
-
client_data = copy.deepcopy(client.__dict__)
|
|
48
|
-
self._db[client.client_id] = client_data
|
|
49
|
-
return True
|
|
50
|
-
|
|
51
|
-
def search_by_value(self, key: str, val: Union[str, bool, int, float]) -> List[Client]:
|
|
52
|
-
"""
|
|
53
|
-
Search for clients by a specific key-value pair in the JSON database.
|
|
54
|
-
|
|
55
|
-
Args:
|
|
56
|
-
key: The key to search by.
|
|
57
|
-
val: The value to search for.
|
|
58
|
-
|
|
59
|
-
Returns:
|
|
60
|
-
A list of clients that match the search criteria.
|
|
61
|
-
"""
|
|
62
|
-
res = []
|
|
63
|
-
if key == "client_id":
|
|
64
|
-
v = self._db.get(val)
|
|
65
|
-
if v:
|
|
66
|
-
res.append(cast2client(v))
|
|
67
|
-
else:
|
|
68
|
-
for client in self._db.values():
|
|
69
|
-
v = client.get(key)
|
|
70
|
-
if v == val:
|
|
71
|
-
res.append(cast2client(client))
|
|
72
|
-
return res
|
|
73
|
-
|
|
74
|
-
def __len__(self) -> int:
|
|
75
|
-
"""
|
|
76
|
-
Get the number of clients in the database.
|
|
77
|
-
|
|
78
|
-
Returns:
|
|
79
|
-
The number of clients in the database.
|
|
80
|
-
"""
|
|
81
|
-
return len(self._db)
|
|
82
|
-
|
|
83
|
-
def __iter__(self) -> Iterable['Client']:
|
|
84
|
-
"""
|
|
85
|
-
Iterate over all clients in the JSON database.
|
|
86
|
-
|
|
87
|
-
Returns:
|
|
88
|
-
An iterator over the clients in the database.
|
|
89
|
-
"""
|
|
90
|
-
for item in self._db.values():
|
|
91
|
-
yield cast2client(item)
|
|
92
|
-
|
|
93
|
-
def commit(self) -> bool:
|
|
94
|
-
"""
|
|
95
|
-
Commit changes to the JSON database.
|
|
96
|
-
|
|
97
|
-
Returns:
|
|
98
|
-
True if the commit was successful, False otherwise.
|
|
99
|
-
"""
|
|
100
|
-
try:
|
|
101
|
-
self._db.store()
|
|
102
|
-
return True
|
|
103
|
-
except Exception as e:
|
|
104
|
-
LOG.error(f"Failed to save {self._db.path} - {e}")
|
|
105
|
-
return False
|
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
from hivemind_plugin_manager.database import Client
|
|
2
|
-
|
|
3
|
-
import json_database.hpm as hpm
|
|
4
|
-
from json_database.hpm import JsonDB
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def make_db(tmp_path, monkeypatch) -> JsonDB:
|
|
8
|
-
"""Return an initialized JsonDB backed by a temp XDG data path."""
|
|
9
|
-
monkeypatch.setattr(hpm, "xdg_data_home", lambda: str(tmp_path))
|
|
10
|
-
return JsonDB()
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def make_client(*, metadata=None, **kwargs) -> Client:
|
|
14
|
-
"""Build a Client with optional metadata."""
|
|
15
|
-
client = Client(**kwargs)
|
|
16
|
-
if metadata is not None:
|
|
17
|
-
client.metadata = metadata
|
|
18
|
-
return client
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def test_hivemind_client_metadata_survives_search_round_trip(tmp_path, monkeypatch):
|
|
22
|
-
"""Client metadata survives add and search in JsonDB."""
|
|
23
|
-
db = make_db(tmp_path, monkeypatch)
|
|
24
|
-
client = make_client(
|
|
25
|
-
client_id=1,
|
|
26
|
-
api_key="alpha-key",
|
|
27
|
-
name="alpha",
|
|
28
|
-
metadata={"owner_id": "owner-123"},
|
|
29
|
-
)
|
|
30
|
-
|
|
31
|
-
assert db.add_item(client)
|
|
32
|
-
found = db.search_by_value("api_key", "alpha-key")
|
|
33
|
-
|
|
34
|
-
assert len(found) == 1
|
|
35
|
-
assert found[0].metadata == {"owner_id": "owner-123"}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def test_hivemind_client_metadata_survives_iteration(tmp_path, monkeypatch):
|
|
39
|
-
"""Client metadata survives iteration in JsonDB."""
|
|
40
|
-
db = make_db(tmp_path, monkeypatch)
|
|
41
|
-
client = make_client(
|
|
42
|
-
client_id=1,
|
|
43
|
-
api_key="alpha-key",
|
|
44
|
-
name="alpha",
|
|
45
|
-
metadata={"owner_id": "owner-123"},
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
assert db.add_item(client)
|
|
49
|
-
found = list(db)
|
|
50
|
-
|
|
51
|
-
assert len(found) == 1
|
|
52
|
-
assert found[0].metadata == {"owner_id": "owner-123"}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def test_hivemind_client_metadata_record_round_trips(tmp_path, monkeypatch):
|
|
56
|
-
"""Stored metadata round-trips through search_by_value."""
|
|
57
|
-
db = make_db(tmp_path, monkeypatch)
|
|
58
|
-
db._db[1] = {
|
|
59
|
-
"client_id": 1,
|
|
60
|
-
"api_key": "alpha-key",
|
|
61
|
-
"name": "alpha",
|
|
62
|
-
"metadata": {"owner_id": "owner-123"},
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
found = db.search_by_value("api_key", "alpha-key")
|
|
66
|
-
|
|
67
|
-
assert len(found) == 1
|
|
68
|
-
assert found[0].api_key == "alpha-key"
|
|
69
|
-
assert found[0].metadata == {"owner_id": "owner-123"}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def test_metadata_defaults_to_empty_when_missing(tmp_path, monkeypatch):
|
|
73
|
-
"""Clients added without a metadata dict get persisted with metadata={}."""
|
|
74
|
-
db = make_db(tmp_path, monkeypatch)
|
|
75
|
-
db.add_item(Client(client_id=1, api_key="k", name="a"))
|
|
76
|
-
assert db._db[1]["metadata"] == {}
|
|
77
|
-
found = db.search_by_value("api_key", "k")
|
|
78
|
-
assert found[0].metadata == {}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
def test_search_by_client_id_returns_metadata(tmp_path, monkeypatch):
|
|
82
|
-
"""The client_id search path also preserves metadata."""
|
|
83
|
-
db = make_db(tmp_path, monkeypatch)
|
|
84
|
-
db.add_item(make_client(client_id=1, api_key="k", name="a",
|
|
85
|
-
metadata={"tier": "gold"}))
|
|
86
|
-
found = db.search_by_value("client_id", 1)
|
|
87
|
-
assert len(found) == 1
|
|
88
|
-
assert found[0].metadata == {"tier": "gold"}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def test_nested_and_non_ascii_metadata_round_trip(tmp_path, monkeypatch):
|
|
92
|
-
"""Nested structures and non-ASCII characters survive add → iterate."""
|
|
93
|
-
db = make_db(tmp_path, monkeypatch)
|
|
94
|
-
meta = {
|
|
95
|
-
"owner": {"id": "owner-1", "tags": ["a", "b"]},
|
|
96
|
-
"name": "Zé Ninguém",
|
|
97
|
-
"emoji": "🚀",
|
|
98
|
-
}
|
|
99
|
-
db.add_item(make_client(client_id=1, api_key="k", name="a", metadata=meta))
|
|
100
|
-
found = list(db)
|
|
101
|
-
assert found[0].metadata == meta
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def test_metadata_survives_commit_and_reload(tmp_path, monkeypatch):
|
|
105
|
-
"""add_item → commit → new JsonDB pointed at the same path reads metadata back."""
|
|
106
|
-
db = make_db(tmp_path, monkeypatch)
|
|
107
|
-
db.add_item(make_client(client_id=1, api_key="k", name="a",
|
|
108
|
-
metadata={"owner": "owner-1"}))
|
|
109
|
-
assert db.commit()
|
|
110
|
-
|
|
111
|
-
# Fresh JsonDB instance against the same xdg_data_home path
|
|
112
|
-
fresh = make_db(tmp_path, monkeypatch)
|
|
113
|
-
found = fresh.search_by_value("api_key", "k")
|
|
114
|
-
assert len(found) == 1
|
|
115
|
-
assert found[0].metadata == {"owner": "owner-1"}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
def test_add_item_snapshots_metadata_against_caller_mutation(tmp_path, monkeypatch):
|
|
119
|
-
"""Caller mutations to client.metadata after add_item must not leak into
|
|
120
|
-
the stored record — including mutations of nested dicts."""
|
|
121
|
-
db = make_db(tmp_path, monkeypatch)
|
|
122
|
-
meta = {"v": "original", "nested": {"k": "n_original"}}
|
|
123
|
-
client = make_client(client_id=1, api_key="k", name="a", metadata=meta)
|
|
124
|
-
db.add_item(client)
|
|
125
|
-
|
|
126
|
-
meta["v"] = "mutated"
|
|
127
|
-
meta["nested"]["k"] = "n_mutated"
|
|
128
|
-
client.metadata["added"] = "later"
|
|
129
|
-
|
|
130
|
-
found = db.search_by_value("api_key", "k")
|
|
131
|
-
assert found[0].metadata == {"v": "original", "nested": {"k": "n_original"}}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def test_add_item_snapshots_list_fields_against_caller_mutation(tmp_path, monkeypatch):
|
|
135
|
-
"""Same aliasing bug applied to all mutable list fields: caller mutation
|
|
136
|
-
of intent_blacklist / skill_blacklist / message_blacklist / allowed_types
|
|
137
|
-
after add_item must not leak into the stored record."""
|
|
138
|
-
db = make_db(tmp_path, monkeypatch)
|
|
139
|
-
intents = ["skill:a"]
|
|
140
|
-
skills = ["skill:b"]
|
|
141
|
-
messages = ["msg:c"]
|
|
142
|
-
allowed = ["recognizer_loop:utterance", "speak:b64_audio"]
|
|
143
|
-
client = Client(
|
|
144
|
-
client_id=1, api_key="k", name="a",
|
|
145
|
-
intent_blacklist=intents,
|
|
146
|
-
skill_blacklist=skills,
|
|
147
|
-
message_blacklist=messages,
|
|
148
|
-
allowed_types=allowed,
|
|
149
|
-
)
|
|
150
|
-
db.add_item(client)
|
|
151
|
-
|
|
152
|
-
# mutate the caller-side lists and the lists still on the client
|
|
153
|
-
intents.append("skill:leaked")
|
|
154
|
-
client.skill_blacklist.append("skill:leaked")
|
|
155
|
-
messages.append("msg:leaked")
|
|
156
|
-
client.allowed_types.append("speak:leaked")
|
|
157
|
-
|
|
158
|
-
found = db.search_by_value("api_key", "k")
|
|
159
|
-
assert found[0].intent_blacklist == ["skill:a"]
|
|
160
|
-
assert found[0].skill_blacklist == ["skill:b"]
|
|
161
|
-
assert found[0].message_blacklist == ["msg:c"]
|
|
162
|
-
# allowed_types: __post_init__ guarantees "recognizer_loop:utterance" is
|
|
163
|
-
# in the list, so verify the leaked entry isn't there.
|
|
164
|
-
assert "speak:leaked" not in found[0].allowed_types
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
def test_add_item_overwrites_metadata_for_same_client_id(tmp_path, monkeypatch):
|
|
168
|
-
"""Re-adding a client with the same client_id replaces stored metadata."""
|
|
169
|
-
db = make_db(tmp_path, monkeypatch)
|
|
170
|
-
db.add_item(make_client(client_id=1, api_key="k", name="a",
|
|
171
|
-
metadata={"v": "old"}))
|
|
172
|
-
db.add_item(make_client(client_id=1, api_key="k", name="a",
|
|
173
|
-
metadata={"v": "new", "extra": "x"}))
|
|
174
|
-
found = db.search_by_value("api_key", "k")
|
|
175
|
-
assert len(found) == 1
|
|
176
|
-
assert found[0].metadata == {"v": "new", "extra": "x"}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{json_database-0.10.2a1 → json_database-1.0.2a1}/json_database.egg-info/dependency_links.txt
RENAMED
|
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
|