scruby 0.5.0__py3-none-any.whl → 0.6.0__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 +5 -3
- scruby/db.py +23 -8
- {scruby-0.5.0.dist-info → scruby-0.6.0.dist-info}/METADATA +23 -22
- scruby-0.6.0.dist-info/RECORD +8 -0
- scruby-0.5.0.dist-info/RECORD +0 -8
- {scruby-0.5.0.dist-info → scruby-0.6.0.dist-info}/WHEEL +0 -0
- {scruby-0.5.0.dist-info → scruby-0.6.0.dist-info}/licenses/LICENSE +0 -0
scruby/__init__.py
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
Scruby is a fast key-value storage library that provides an ordered mapping from string keys to string values.
|
|
4
4
|
The library uses fractal-tree addressing.
|
|
5
5
|
|
|
6
|
-
The
|
|
6
|
+
The database consists of collections.
|
|
7
|
+
The maximum size of the one collection is 16**8=4294967296 branches,
|
|
7
8
|
each branch can store one or more keys.
|
|
8
9
|
|
|
9
|
-
The value of any key can be obtained in
|
|
10
|
-
|
|
10
|
+
The value of any key in collection can be obtained in 8 steps, thereby achieving high performance.
|
|
11
|
+
|
|
12
|
+
In the future, to search by value of key, the use of a quantum loop is supposed.
|
|
11
13
|
"""
|
|
12
14
|
|
|
13
15
|
from __future__ import annotations
|
scruby/db.py
CHANGED
|
@@ -4,7 +4,8 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
__all__ = ("Scruby",)
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
import contextlib
|
|
8
|
+
import zlib
|
|
8
9
|
from shutil import rmtree
|
|
9
10
|
from typing import TypeVar
|
|
10
11
|
|
|
@@ -29,19 +30,31 @@ class Scruby[T]:
|
|
|
29
30
|
) -> None:
|
|
30
31
|
self.__class_model = class_model
|
|
31
32
|
|
|
33
|
+
def check_key(self, key: str) -> None:
|
|
34
|
+
"""Check the key."""
|
|
35
|
+
if not isinstance(key, str):
|
|
36
|
+
raise KeyError("The key is not a type of `str`.")
|
|
37
|
+
if len(key) == 0:
|
|
38
|
+
raise KeyError("The key should not be empty.")
|
|
39
|
+
|
|
32
40
|
async def get_leaf_path(self, key: str) -> Path:
|
|
33
41
|
"""Get the path to the database cell by key.
|
|
34
42
|
|
|
35
43
|
Args:
|
|
36
44
|
key: Key name.
|
|
37
45
|
"""
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
46
|
+
self.check_key(key)
|
|
47
|
+
# Key to crc32 sum.
|
|
48
|
+
key_crc32: str = f"{zlib.crc32(key.encode('utf-8')):08x}"
|
|
49
|
+
# Convert crc32 sum in the segment of path.
|
|
50
|
+
separated_crc32: str = "/".join(list(key_crc32))
|
|
42
51
|
# The path of the branch to the database.
|
|
43
52
|
branch_path: Path = Path(
|
|
44
|
-
*(
|
|
53
|
+
*(
|
|
54
|
+
constants.DB_ROOT,
|
|
55
|
+
self.__class_model.__name__,
|
|
56
|
+
separated_crc32,
|
|
57
|
+
),
|
|
45
58
|
)
|
|
46
59
|
# If the branch does not exist, need to create it.
|
|
47
60
|
if not await branch_path.exists():
|
|
@@ -127,7 +140,8 @@ class Scruby[T]:
|
|
|
127
140
|
return
|
|
128
141
|
raise KeyError()
|
|
129
142
|
|
|
130
|
-
|
|
143
|
+
@classmethod
|
|
144
|
+
async def napalm(cls) -> None:
|
|
131
145
|
"""Asynchronous method for full database deletion (Arg: db_name).
|
|
132
146
|
|
|
133
147
|
The main purpose is tests.
|
|
@@ -135,5 +149,6 @@ class Scruby[T]:
|
|
|
135
149
|
Warning:
|
|
136
150
|
- `Be careful, this will remove all keys.`
|
|
137
151
|
"""
|
|
138
|
-
|
|
152
|
+
with contextlib.suppress(FileNotFoundError):
|
|
153
|
+
await to_thread.run_sync(rmtree, constants.DB_ROOT)
|
|
139
154
|
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scruby
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
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
|
|
@@ -27,7 +27,9 @@ Classifier: Typing :: Typed
|
|
|
27
27
|
Requires-Python: <4.0,>=3.12
|
|
28
28
|
Requires-Dist: anyio>=4.10.0
|
|
29
29
|
Requires-Dist: orjson>=3.11.3
|
|
30
|
-
Requires-Dist:
|
|
30
|
+
Requires-Dist: phonenumbers>=9.0.13
|
|
31
|
+
Requires-Dist: pydantic-extra-types>=2.10.5
|
|
32
|
+
Requires-Dist: pydantic[email]>=2.11.7
|
|
31
33
|
Description-Content-Type: text/markdown
|
|
32
34
|
|
|
33
35
|
<div align="center">
|
|
@@ -64,15 +66,15 @@ Description-Content-Type: text/markdown
|
|
|
64
66
|
</p>
|
|
65
67
|
<p align="center">
|
|
66
68
|
Scruby is a fast key-value storage library that provides an ordered mapping from string keys to string values.
|
|
67
|
-
<br>
|
|
68
69
|
The library uses fractal-tree addressing.
|
|
69
70
|
<br>
|
|
70
|
-
The
|
|
71
|
+
The database consists of collections.
|
|
72
|
+
The maximum size of the one collection is 16**8=4294967296 branches,
|
|
71
73
|
each branch can store one or more keys.
|
|
72
74
|
<br>
|
|
73
|
-
The value of any key can be obtained in
|
|
75
|
+
The value of any key in collection can be obtained in 8 steps, thereby achieving high performance.
|
|
74
76
|
<br>
|
|
75
|
-
|
|
77
|
+
In the future, to search by value of key, the use of a quantum loop is supposed.
|
|
76
78
|
</p>
|
|
77
79
|
</p>
|
|
78
80
|
</div>
|
|
@@ -96,23 +98,24 @@ uv add scruby
|
|
|
96
98
|
```python
|
|
97
99
|
import anyio
|
|
98
100
|
import datetime
|
|
99
|
-
from pydantic import BaseModel
|
|
101
|
+
from pydantic import BaseModel, EmailStr
|
|
102
|
+
from pydantic_extra_types.phone_numbers import PhoneNumber
|
|
100
103
|
from scruby import Scruby, constants
|
|
101
104
|
|
|
102
105
|
constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
|
|
103
106
|
|
|
104
107
|
class User(BaseModel):
|
|
105
108
|
"""Model of User."""
|
|
106
|
-
|
|
107
109
|
first_name: str
|
|
108
110
|
last_name: str
|
|
109
111
|
birthday: datetime.datetime
|
|
110
|
-
email:
|
|
111
|
-
phone:
|
|
112
|
+
email: EmailStr
|
|
113
|
+
phone: PhoneNumber
|
|
112
114
|
|
|
113
115
|
async def main() -> None:
|
|
114
116
|
"""Example."""
|
|
115
|
-
|
|
117
|
+
# Get collection of `User`.
|
|
118
|
+
user_coll = Scruby(User)
|
|
116
119
|
|
|
117
120
|
user = User(
|
|
118
121
|
first_name="John",
|
|
@@ -122,23 +125,21 @@ async def main() -> None:
|
|
|
122
125
|
phone="+447986123456",
|
|
123
126
|
)
|
|
124
127
|
|
|
125
|
-
await
|
|
128
|
+
await user_coll.set_key("+447986123456", user)
|
|
126
129
|
|
|
127
|
-
await
|
|
128
|
-
await
|
|
130
|
+
await user_coll.get_key("+447986123456") # => user
|
|
131
|
+
await user_coll.get_key("key missing") # => KeyError
|
|
129
132
|
|
|
130
|
-
await
|
|
131
|
-
await
|
|
133
|
+
await user_coll.has_key("+447986123456") # => True
|
|
134
|
+
await user_coll.has_key("key missing") # => False
|
|
132
135
|
|
|
133
|
-
await
|
|
134
|
-
await
|
|
135
|
-
await
|
|
136
|
+
await user_coll.delete_key("+447986123456")
|
|
137
|
+
await user_coll.delete_key("+447986123456") # => KeyError
|
|
138
|
+
await user_coll.delete_key("key missing") # => KeyError
|
|
136
139
|
|
|
137
140
|
# Full database deletion.
|
|
138
141
|
# Hint: The main purpose is tests.
|
|
139
|
-
await
|
|
140
|
-
await db.napalm() # => FileNotFoundError
|
|
141
|
-
|
|
142
|
+
await Scruby.napalm()
|
|
142
143
|
|
|
143
144
|
if __name__ == "__main__":
|
|
144
145
|
anyio.run(main)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
scruby/__init__.py,sha256=Mvy-90k-kNUAlYA7xuCEIT1uC8u5pepuDxGy6DglCxU,689
|
|
2
|
+
scruby/constants.py,sha256=kwF0FIbeChBxsNxOCQhMsDEn1lakD7MIQKJ-PHYeSAo,328
|
|
3
|
+
scruby/db.py,sha256=Xn7AWXly8nubvWqsRrJYpvozUHB1CXNineizVK6GNEw,4854
|
|
4
|
+
scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
+
scruby-0.6.0.dist-info/METADATA,sha256=2mxPkFwKcU2V-Mw6nz_fru7xo-TVdugS5XUPNYoJONg,6751
|
|
6
|
+
scruby-0.6.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
+
scruby-0.6.0.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
|
|
8
|
+
scruby-0.6.0.dist-info/RECORD,,
|
scruby-0.5.0.dist-info/RECORD
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
scruby/__init__.py,sha256=LnHBN1pIOtT89baSQoknQwYI1cy-hmN1Lo0k8o1Ms48,659
|
|
2
|
-
scruby/constants.py,sha256=kwF0FIbeChBxsNxOCQhMsDEn1lakD7MIQKJ-PHYeSAo,328
|
|
3
|
-
scruby/db.py,sha256=iG1D4-ncVrVysp7OXH-eZksnNacjNna4_8nUbMkWnSE,4409
|
|
4
|
-
scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
|
-
scruby-0.5.0.dist-info/METADATA,sha256=6V1NV3KWNRsc2Gb2cZbBQ4VsLYbIDMWkCiM9CjkJyxo,6509
|
|
6
|
-
scruby-0.5.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
7
|
-
scruby-0.5.0.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
|
|
8
|
-
scruby-0.5.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|