scruby 0.1.1__py3-none-any.whl → 0.1.3__py3-none-any.whl
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 scruby might be problematic. Click here for more details.
- scruby/__init__.py +1 -193
- scruby/db.py +214 -0
- {scruby-0.1.1.dist-info → scruby-0.1.3.dist-info}/METADATA +2 -1
- scruby-0.1.3.dist-info/RECORD +7 -0
- scruby-0.1.1.dist-info/RECORD +0 -6
- {scruby-0.1.1.dist-info → scruby-0.1.3.dist-info}/WHEEL +0 -0
- {scruby-0.1.1.dist-info → scruby-0.1.3.dist-info}/licenses/LICENSE +0 -0
scruby/__init__.py
CHANGED
|
@@ -14,196 +14,4 @@ from __future__ import annotations
|
|
|
14
14
|
|
|
15
15
|
__all__ = ("Scruby",)
|
|
16
16
|
|
|
17
|
-
import
|
|
18
|
-
from shutil import rmtree
|
|
19
|
-
from typing import Literal
|
|
20
|
-
|
|
21
|
-
import orjson
|
|
22
|
-
from anyio import Path, to_thread
|
|
23
|
-
|
|
24
|
-
type ValueOfKey = str | int | float | list | dict | Literal[True] | Literal[False] | None
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class Scruby:
|
|
28
|
-
"""Creation and management of the database.
|
|
29
|
-
|
|
30
|
-
Example:
|
|
31
|
-
>>> from scruby import Scruby
|
|
32
|
-
>>> db = Scruby()
|
|
33
|
-
>>> await db.set_key("key name", "Some text")
|
|
34
|
-
None
|
|
35
|
-
>>> await db.get_key("key name")
|
|
36
|
-
"Some text"
|
|
37
|
-
>>> await db.has_key("key name")
|
|
38
|
-
True
|
|
39
|
-
>>> await db.delete_key("key name")
|
|
40
|
-
None
|
|
41
|
-
>>> await db.napalm()
|
|
42
|
-
None
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
db_path: Path to root directory of databases. Defaule by = "ScrubyDB" (in root of project)
|
|
46
|
-
"""
|
|
47
|
-
|
|
48
|
-
def __init__( # noqa: D107
|
|
49
|
-
self,
|
|
50
|
-
db_path: str = "ScrubyDB",
|
|
51
|
-
) -> None:
|
|
52
|
-
super().__init__()
|
|
53
|
-
self.__db_path = db_path
|
|
54
|
-
|
|
55
|
-
@property
|
|
56
|
-
def db_path(self) -> str:
|
|
57
|
-
"""Get database name."""
|
|
58
|
-
return self.__db_path
|
|
59
|
-
|
|
60
|
-
async def get_leaf_path(self, key: str) -> Path:
|
|
61
|
-
"""Get the path to the database cell by key.
|
|
62
|
-
|
|
63
|
-
Args:
|
|
64
|
-
key: Key name.
|
|
65
|
-
"""
|
|
66
|
-
# Key to md5 sum.
|
|
67
|
-
key_md5: str = hashlib.md5(key.encode("utf-8")).hexdigest() # noqa: S324
|
|
68
|
-
# Convert md5 sum in the segment of path.
|
|
69
|
-
segment_path_md5: str = "/".join(list(key_md5))
|
|
70
|
-
# The path of the branch to the database.
|
|
71
|
-
branch_path: Path = Path(
|
|
72
|
-
*(self.__db_path, segment_path_md5),
|
|
73
|
-
)
|
|
74
|
-
# If the branch does not exist, need to create it.
|
|
75
|
-
if not await branch_path.exists():
|
|
76
|
-
await branch_path.mkdir(parents=True)
|
|
77
|
-
# The path to the database cell.
|
|
78
|
-
leaf_path: Path = Path(*(branch_path, "leaf.json"))
|
|
79
|
-
return leaf_path
|
|
80
|
-
|
|
81
|
-
async def set_key(
|
|
82
|
-
self,
|
|
83
|
-
key: str,
|
|
84
|
-
value: ValueOfKey,
|
|
85
|
-
) -> None:
|
|
86
|
-
"""Asynchronous method for adding and updating keys to database.
|
|
87
|
-
|
|
88
|
-
Example:
|
|
89
|
-
>>> from scruby import Scruby
|
|
90
|
-
>>> db = Scruby()
|
|
91
|
-
>>> await db.set_key("key name", "Some text")
|
|
92
|
-
None
|
|
93
|
-
|
|
94
|
-
Args:
|
|
95
|
-
key: Key name.
|
|
96
|
-
value: Value of key.
|
|
97
|
-
"""
|
|
98
|
-
# The path to the database cell.
|
|
99
|
-
leaf_path: Path = await self.get_leaf_path(key)
|
|
100
|
-
# Write key-value to the database.
|
|
101
|
-
if await leaf_path.exists():
|
|
102
|
-
# Add new key or update existing.
|
|
103
|
-
data_json: bytes = await leaf_path.read_bytes()
|
|
104
|
-
data: dict = orjson.loads(data_json) or {}
|
|
105
|
-
data[key] = value
|
|
106
|
-
await leaf_path.write_bytes(orjson.dumps(data))
|
|
107
|
-
else:
|
|
108
|
-
# Add new key to a blank leaf.
|
|
109
|
-
await leaf_path.write_bytes(data=orjson.dumps({key: value}))
|
|
110
|
-
|
|
111
|
-
async def get_key(self, key: str) -> ValueOfKey:
|
|
112
|
-
"""Asynchronous method for getting key from database.
|
|
113
|
-
|
|
114
|
-
Example:
|
|
115
|
-
>>> from scruby import Scruby
|
|
116
|
-
>>> db = Scruby()
|
|
117
|
-
>>> await db.set_key("key name", "Some text")
|
|
118
|
-
None
|
|
119
|
-
>>> await db.get_key("key name")
|
|
120
|
-
"Some text"
|
|
121
|
-
>>> await db.get_key("key missing")
|
|
122
|
-
KeyError
|
|
123
|
-
|
|
124
|
-
Args:
|
|
125
|
-
key: Key name.
|
|
126
|
-
"""
|
|
127
|
-
# The path to the database cell.
|
|
128
|
-
leaf_path: Path = await self.get_leaf_path(key)
|
|
129
|
-
# Get value of key.
|
|
130
|
-
if await leaf_path.exists():
|
|
131
|
-
data_json: bytes = await leaf_path.read_bytes()
|
|
132
|
-
data: dict = orjson.loads(data_json) or {}
|
|
133
|
-
return data[key]
|
|
134
|
-
raise KeyError()
|
|
135
|
-
|
|
136
|
-
async def has_key(self, key: str) -> bool:
|
|
137
|
-
"""Asynchronous method for checking presence of key in database.
|
|
138
|
-
|
|
139
|
-
Example:
|
|
140
|
-
>>> from scruby import Scruby
|
|
141
|
-
>>> db = Scruby()
|
|
142
|
-
>>> await db.set_key("key name", "Some text")
|
|
143
|
-
None
|
|
144
|
-
>>> await db.has_key("key name")
|
|
145
|
-
True
|
|
146
|
-
>>> await db.has_key("key missing")
|
|
147
|
-
False
|
|
148
|
-
|
|
149
|
-
Args:
|
|
150
|
-
key: Key name.
|
|
151
|
-
"""
|
|
152
|
-
# The path to the database cell.
|
|
153
|
-
leaf_path: Path = await self.get_leaf_path(key)
|
|
154
|
-
# Checking whether there is a key.
|
|
155
|
-
if await leaf_path.exists():
|
|
156
|
-
data_json: bytes = await leaf_path.read_bytes()
|
|
157
|
-
data: dict = orjson.loads(data_json) or {}
|
|
158
|
-
try:
|
|
159
|
-
data[key]
|
|
160
|
-
return True
|
|
161
|
-
except KeyError:
|
|
162
|
-
return False
|
|
163
|
-
return False
|
|
164
|
-
|
|
165
|
-
async def delete_key(self, key: str) -> None:
|
|
166
|
-
"""Asynchronous method for deleting key from database.
|
|
167
|
-
|
|
168
|
-
Example:
|
|
169
|
-
>>> from scruby import Scruby
|
|
170
|
-
>>> db = Scruby()
|
|
171
|
-
>>> await db.set_key("key name", "Some text")
|
|
172
|
-
None
|
|
173
|
-
>>> await db.delete_key("key name")
|
|
174
|
-
None
|
|
175
|
-
>>> await db.delete_key("key missing")
|
|
176
|
-
KeyError
|
|
177
|
-
|
|
178
|
-
Args:
|
|
179
|
-
key: Key name.
|
|
180
|
-
"""
|
|
181
|
-
# The path to the database cell.
|
|
182
|
-
leaf_path: Path = await self.get_leaf_path(key)
|
|
183
|
-
# Deleting key.
|
|
184
|
-
if await leaf_path.exists():
|
|
185
|
-
data_json: bytes = await leaf_path.read_bytes()
|
|
186
|
-
data: dict = orjson.loads(data_json) or {}
|
|
187
|
-
del data[key]
|
|
188
|
-
await leaf_path.write_bytes(orjson.dumps(data))
|
|
189
|
-
return
|
|
190
|
-
raise KeyError()
|
|
191
|
-
|
|
192
|
-
async def napalm(self) -> None:
|
|
193
|
-
"""Asynchronous method for full database deletion (Arg: db_path).
|
|
194
|
-
|
|
195
|
-
Warning:
|
|
196
|
-
- `Be careful, this will remove all keys.`
|
|
197
|
-
|
|
198
|
-
Example:
|
|
199
|
-
>>> from scruby import Scruby
|
|
200
|
-
>>> db = Scruby()
|
|
201
|
-
>>> await db.set_key("key name", "Some text")
|
|
202
|
-
None
|
|
203
|
-
>>> await db.napalm()
|
|
204
|
-
None
|
|
205
|
-
>>> await db.napalm()
|
|
206
|
-
FileNotFoundError
|
|
207
|
-
"""
|
|
208
|
-
await to_thread.run_sync(rmtree, self.__db_path)
|
|
209
|
-
return
|
|
17
|
+
from scruby.db import Scruby
|
scruby/db.py
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
"""Creation and management of the database.
|
|
2
|
+
|
|
3
|
+
Examples:
|
|
4
|
+
>>> from scruby import Scruby
|
|
5
|
+
>>> db = Scruby()
|
|
6
|
+
>>> await db.set_key("key name", "Some text")
|
|
7
|
+
None
|
|
8
|
+
>>> await db.get_key("key name")
|
|
9
|
+
"Some text"
|
|
10
|
+
>>> await db.has_key("key name")
|
|
11
|
+
True
|
|
12
|
+
>>> await db.delete_key("key name")
|
|
13
|
+
None
|
|
14
|
+
>>> await db.napalm()
|
|
15
|
+
None
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
__all__ = ("Scruby",)
|
|
21
|
+
|
|
22
|
+
import hashlib
|
|
23
|
+
from shutil import rmtree
|
|
24
|
+
from typing import Literal
|
|
25
|
+
|
|
26
|
+
import orjson
|
|
27
|
+
from anyio import Path, to_thread
|
|
28
|
+
|
|
29
|
+
type ValueOfKey = str | int | float | list | dict | Literal[True] | Literal[False] | None
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Scruby:
|
|
33
|
+
"""Creation and management of the database.
|
|
34
|
+
|
|
35
|
+
Examples:
|
|
36
|
+
>>> from scruby import Scruby
|
|
37
|
+
>>> db = Scruby()
|
|
38
|
+
>>> await db.set_key("key name", "Some text")
|
|
39
|
+
None
|
|
40
|
+
>>> await db.get_key("key name")
|
|
41
|
+
"Some text"
|
|
42
|
+
>>> await db.has_key("key name")
|
|
43
|
+
True
|
|
44
|
+
>>> await db.delete_key("key name")
|
|
45
|
+
None
|
|
46
|
+
>>> await db.napalm()
|
|
47
|
+
None
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
db_path: Path to root directory of databases. Defaule by = "ScrubyDB" (in root of project)
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__( # noqa: D107
|
|
54
|
+
self,
|
|
55
|
+
db_path: str = "ScrubyDB",
|
|
56
|
+
) -> None:
|
|
57
|
+
super().__init__()
|
|
58
|
+
self.__db_path = db_path
|
|
59
|
+
|
|
60
|
+
@property
|
|
61
|
+
def db_path(self) -> str:
|
|
62
|
+
"""Get database name."""
|
|
63
|
+
return self.__db_path
|
|
64
|
+
|
|
65
|
+
async def get_leaf_path(self, key: str) -> Path:
|
|
66
|
+
"""Get the path to the database cell by key.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
key: Key name.
|
|
70
|
+
"""
|
|
71
|
+
# Key to md5 sum.
|
|
72
|
+
key_md5: str = hashlib.md5(key.encode("utf-8")).hexdigest() # noqa: S324
|
|
73
|
+
# Convert md5 sum in the segment of path.
|
|
74
|
+
segment_path_md5: str = "/".join(list(key_md5))
|
|
75
|
+
# The path of the branch to the database.
|
|
76
|
+
branch_path: Path = Path(
|
|
77
|
+
*(self.__db_path, segment_path_md5),
|
|
78
|
+
)
|
|
79
|
+
# If the branch does not exist, need to create it.
|
|
80
|
+
if not await branch_path.exists():
|
|
81
|
+
await branch_path.mkdir(parents=True)
|
|
82
|
+
# The path to the database cell.
|
|
83
|
+
leaf_path: Path = Path(*(branch_path, "leaf.json"))
|
|
84
|
+
return leaf_path
|
|
85
|
+
|
|
86
|
+
async def set_key(
|
|
87
|
+
self,
|
|
88
|
+
key: str,
|
|
89
|
+
value: ValueOfKey,
|
|
90
|
+
) -> None:
|
|
91
|
+
"""Asynchronous method for adding and updating keys to database.
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
>>> from scruby import Scruby
|
|
95
|
+
>>> db = Scruby()
|
|
96
|
+
>>> await db.set_key("key name", "Some text")
|
|
97
|
+
None
|
|
98
|
+
|
|
99
|
+
Args:
|
|
100
|
+
key: Key name.
|
|
101
|
+
value: Value of key.
|
|
102
|
+
"""
|
|
103
|
+
# The path to the database cell.
|
|
104
|
+
leaf_path: Path = await self.get_leaf_path(key)
|
|
105
|
+
# Write key-value to the database.
|
|
106
|
+
if await leaf_path.exists():
|
|
107
|
+
# Add new key or update existing.
|
|
108
|
+
data_json: bytes = await leaf_path.read_bytes()
|
|
109
|
+
data: dict = orjson.loads(data_json) or {}
|
|
110
|
+
data[key] = value
|
|
111
|
+
await leaf_path.write_bytes(orjson.dumps(data))
|
|
112
|
+
else:
|
|
113
|
+
# Add new key to a blank leaf.
|
|
114
|
+
await leaf_path.write_bytes(data=orjson.dumps({key: value}))
|
|
115
|
+
|
|
116
|
+
async def get_key(self, key: str) -> ValueOfKey:
|
|
117
|
+
"""Asynchronous method for getting key from database.
|
|
118
|
+
|
|
119
|
+
Examples:
|
|
120
|
+
>>> from scruby import Scruby
|
|
121
|
+
>>> db = Scruby()
|
|
122
|
+
>>> await db.set_key("key name", "Some text")
|
|
123
|
+
None
|
|
124
|
+
>>> await db.get_key("key name")
|
|
125
|
+
"Some text"
|
|
126
|
+
>>> await db.get_key("key missing")
|
|
127
|
+
KeyError
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
key: Key name.
|
|
131
|
+
"""
|
|
132
|
+
# The path to the database cell.
|
|
133
|
+
leaf_path: Path = await self.get_leaf_path(key)
|
|
134
|
+
# Get value of key.
|
|
135
|
+
if await leaf_path.exists():
|
|
136
|
+
data_json: bytes = await leaf_path.read_bytes()
|
|
137
|
+
data: dict = orjson.loads(data_json) or {}
|
|
138
|
+
return data[key]
|
|
139
|
+
raise KeyError()
|
|
140
|
+
|
|
141
|
+
async def has_key(self, key: str) -> bool:
|
|
142
|
+
"""Asynchronous method for checking presence of key in database.
|
|
143
|
+
|
|
144
|
+
Examples:
|
|
145
|
+
>>> from scruby import Scruby
|
|
146
|
+
>>> db = Scruby()
|
|
147
|
+
>>> await db.set_key("key name", "Some text")
|
|
148
|
+
None
|
|
149
|
+
>>> await db.has_key("key name")
|
|
150
|
+
True
|
|
151
|
+
>>> await db.has_key("key missing")
|
|
152
|
+
False
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
key: Key name.
|
|
156
|
+
"""
|
|
157
|
+
# The path to the database cell.
|
|
158
|
+
leaf_path: Path = await self.get_leaf_path(key)
|
|
159
|
+
# Checking whether there is a key.
|
|
160
|
+
if await leaf_path.exists():
|
|
161
|
+
data_json: bytes = await leaf_path.read_bytes()
|
|
162
|
+
data: dict = orjson.loads(data_json) or {}
|
|
163
|
+
try:
|
|
164
|
+
data[key]
|
|
165
|
+
return True
|
|
166
|
+
except KeyError:
|
|
167
|
+
return False
|
|
168
|
+
return False
|
|
169
|
+
|
|
170
|
+
async def delete_key(self, key: str) -> None:
|
|
171
|
+
"""Asynchronous method for deleting key from database.
|
|
172
|
+
|
|
173
|
+
Examples:
|
|
174
|
+
>>> from scruby import Scruby
|
|
175
|
+
>>> db = Scruby()
|
|
176
|
+
>>> await db.set_key("key name", "Some text")
|
|
177
|
+
None
|
|
178
|
+
>>> await db.delete_key("key name")
|
|
179
|
+
None
|
|
180
|
+
>>> await db.delete_key("key missing")
|
|
181
|
+
KeyError
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
key: Key name.
|
|
185
|
+
"""
|
|
186
|
+
# The path to the database cell.
|
|
187
|
+
leaf_path: Path = await self.get_leaf_path(key)
|
|
188
|
+
# Deleting key.
|
|
189
|
+
if await leaf_path.exists():
|
|
190
|
+
data_json: bytes = await leaf_path.read_bytes()
|
|
191
|
+
data: dict = orjson.loads(data_json) or {}
|
|
192
|
+
del data[key]
|
|
193
|
+
await leaf_path.write_bytes(orjson.dumps(data))
|
|
194
|
+
return
|
|
195
|
+
raise KeyError()
|
|
196
|
+
|
|
197
|
+
async def napalm(self) -> None:
|
|
198
|
+
"""Asynchronous method for full database deletion (Arg: db_path).
|
|
199
|
+
|
|
200
|
+
Warning:
|
|
201
|
+
- `Be careful, this will remove all keys.`
|
|
202
|
+
|
|
203
|
+
Examples:
|
|
204
|
+
>>> from scruby import Scruby
|
|
205
|
+
>>> db = Scruby()
|
|
206
|
+
>>> await db.set_key("key name", "Some text")
|
|
207
|
+
None
|
|
208
|
+
>>> await db.napalm()
|
|
209
|
+
None
|
|
210
|
+
>>> await db.napalm()
|
|
211
|
+
FileNotFoundError
|
|
212
|
+
"""
|
|
213
|
+
await to_thread.run_sync(rmtree, self.__db_path)
|
|
214
|
+
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scruby
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: A fast key-value storage library.
|
|
5
5
|
Project-URL: Homepage, https://github.com/kebasyaty/scruby
|
|
6
6
|
Project-URL: Repository, https://github.com/kebasyaty/scruby
|
|
@@ -108,6 +108,7 @@ async def main() -> None:
|
|
|
108
108
|
await db.has_key("key missing") # => False
|
|
109
109
|
await db.delete_key("key name")
|
|
110
110
|
await db.delete_key("key missing") # => KeyError
|
|
111
|
+
# Full database deletion.
|
|
111
112
|
await db.napalm()
|
|
112
113
|
await db.napalm() # => FileNotFoundError
|
|
113
114
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
scruby/__init__.py,sha256=TCxUjBI5A0KZcwvfmgaBVl8ScuzzOVvALl_T4iqSR9c,603
|
|
2
|
+
scruby/db.py,sha256=otENL-t7ie_8Fgzcteh2WsXFPu9pM4DBUdO_2GB1vwk,6565
|
|
3
|
+
scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
scruby-0.1.3.dist-info/METADATA,sha256=r3Z7483vuN5jtps1-6g0Tydj7POgc-rQWMeAK9YeoPM,5906
|
|
5
|
+
scruby-0.1.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
scruby-0.1.3.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
|
|
7
|
+
scruby-0.1.3.dist-info/RECORD,,
|
scruby-0.1.1.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
scruby/__init__.py,sha256=5_WsWLxxGQ8LYi0XrZc7S5P3HmaP1wfvb9VUdrVxvmM,6694
|
|
2
|
-
scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
scruby-0.1.1.dist-info/METADATA,sha256=hxsrER-Z7_Qa8ThH0Tn8XPCw-vvoSHuCHZ24cROmYyk,5876
|
|
4
|
-
scruby-0.1.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
5
|
-
scruby-0.1.1.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
|
|
6
|
-
scruby-0.1.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|