scruby 0.9.0__py3-none-any.whl → 0.17.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.
scruby/errors.py ADDED
@@ -0,0 +1,39 @@
1
+ """Scruby Exceptions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ __all__ = (
6
+ "ScrubyException",
7
+ "MetadataValueError",
8
+ )
9
+
10
+
11
+ class ScrubyException(Exception):
12
+ """Root Custom Exception."""
13
+
14
+ def __init__(self, *args, **kwargs) -> None: # type: ignore[no-untyped-def] # noqa: D107
15
+ super().__init__(*args, **kwargs)
16
+
17
+
18
+ class MetadataValueError(ScrubyException):
19
+ """Exception is raised if value of variable in metadata does not matching expected."""
20
+
21
+ def __init__(self, message: str) -> None: # noqa: D107
22
+ self.message = message
23
+ super().__init__(self.message)
24
+
25
+
26
+ class KeyAlreadyExistsError(ScrubyException):
27
+ """Exception is raised if the key already exists."""
28
+
29
+ def __init__(self) -> None:
30
+ self.message = "The key already exists."
31
+ super().__init__(self.message)
32
+
33
+
34
+ class KeyNotExistsError(ScrubyException):
35
+ """Exception is raised If the key is not exists."""
36
+
37
+ def __init__(self) -> None:
38
+ self.message = "The key not exists."
39
+ super().__init__(self.message)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scruby
3
- Version: 0.9.0
3
+ Version: 0.17.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
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3
21
21
  Classifier: Programming Language :: Python :: 3 :: Only
22
22
  Classifier: Programming Language :: Python :: 3.12
23
23
  Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Programming Language :: Python :: 3.14
24
25
  Classifier: Programming Language :: Python :: Implementation :: CPython
25
26
  Classifier: Topic :: Database
26
27
  Classifier: Typing :: Typed
@@ -43,7 +44,7 @@ Description-Content-Type: text/markdown
43
44
  </p>
44
45
  <p>
45
46
  <h1>Scruby</h1>
46
- <h3>A fast key-value storage library.</h3>
47
+ <h3>Asynchronous library for building and managing a hybrid database,<br>by scheme of key-value.</h3>
47
48
  <p align="center">
48
49
  <a href="https://github.com/kebasyaty/scruby/actions/workflows/test.yml" alt="Build Status"><img src="https://github.com/kebasyaty/scruby/actions/workflows/test.yml/badge.svg" alt="Build Status"></a>
49
50
  <a href="https://kebasyaty.github.io/scruby/" alt="Docs"><img src="https://img.shields.io/badge/docs-available-brightgreen.svg" alt="Docs"></a>
@@ -51,34 +52,30 @@ Description-Content-Type: text/markdown
51
52
  <a href="https://pypi.python.org/pypi/scruby/" alt="PyPI status"><img src="https://img.shields.io/pypi/status/scruby.svg" alt="PyPI status"></a>
52
53
  <a href="https://pypi.python.org/pypi/scruby/" alt="PyPI version fury.io"><img src="https://badge.fury.io/py/scruby.svg" alt="PyPI version fury.io"></a>
53
54
  <br>
54
- <a href="https://github.com/kebasyaty/scruby/issues"><img src="https://img.shields.io/github/issues/kebasyaty/scruby.svg" alt="GitHub issues"></a>
55
- <a href="https://pepy.tech/projects/scruby"><img src="https://static.pepy.tech/badge/scruby" alt="PyPI Downloads"></a>
56
- <a href="https://github.com/kebasyaty/scruby/blob/main/LICENSE" alt="GitHub license"><img src="https://img.shields.io/github/license/kebasyaty/scruby" alt="GitHub license"></a>
57
55
  <a href="https://mypy-lang.org/" alt="Types: Mypy"><img src="https://img.shields.io/badge/types-Mypy-202235.svg?color=0c7ebf" alt="Types: Mypy"></a>
58
56
  <a href="https://docs.astral.sh/ruff/" alt="Code style: Ruff"><img src="https://img.shields.io/badge/code%20style-Ruff-FDD835.svg" alt="Code style: Ruff"></a>
59
- <a href="https://github.com/kebasyaty/scruby" alt="PyPI implementation"><img src="https://img.shields.io/pypi/implementation/scruby" alt="PyPI implementation"></a>
60
- <br>
61
57
  <a href="https://pypi.org/project/scruby"><img src="https://img.shields.io/pypi/format/scruby" alt="Format"></a>
62
- <a href="https://github.com/kebasyaty/scruby"><img src="https://img.shields.io/github/languages/top/kebasyaty/scruby" alt="Top"></a>
63
- <a href="https://github.com/kebasyaty/scruby"><img src="https://img.shields.io/github/repo-size/kebasyaty/scruby" alt="Size"></a>
64
- <a href="https://github.com/kebasyaty/scruby"><img src="https://img.shields.io/github/last-commit/kebasyaty/scruby/main" alt="Last commit"></a>
65
- <a href="https://github.com/kebasyaty/scruby/releases/" alt="GitHub release"><img src="https://img.shields.io/github/release/kebasyaty/scruby" alt="GitHub release"></a>
58
+ <a href="https://pepy.tech/projects/scruby"><img src="https://static.pepy.tech/badge/scruby" alt="PyPI Downloads"></a>
59
+ <a href="https://github.com/kebasyaty/scruby/blob/main/LICENSE" alt="GitHub license"><img src="https://img.shields.io/github/license/kebasyaty/scruby" alt="GitHub license"></a>
66
60
  </p>
67
61
  <p align="center">
68
- Scruby is a fast key-value storage asynchronous library that provides an
69
- <br>
70
- ordered mapping from string keys to string values.
71
- <br>
72
- The library uses fractal-tree addressing.
73
- <br>
74
- The database consists of collections.
75
- <br>
76
- The maximum size of the one collection is 16**8=4294967296 branches,
77
- each branch can store one or more keys.
78
- <br>
79
- The value of any key in collection can be obtained in 8 steps, thereby achieving high performance.
80
- <br>
81
- In the future, to search by value of key, the use of a quantum loop is supposed.
62
+ The library uses fractal-tree addressing and
63
+ <br>
64
+ the search for documents based on the effect of a quantum loop.
65
+ <br>
66
+ The database consists of collections.
67
+ <br>
68
+ The maximum size of the one collection is 16\*\*8=4294967296 branches,
69
+ <br>
70
+ each branch can store one or more keys.
71
+ <br>
72
+ The value of any key in collection can be obtained in 8 steps,
73
+ <br>
74
+ thereby achieving high performance.
75
+ <br>
76
+ The effectiveness of the search for documents based on a quantum loop,
77
+ <br>
78
+ requires a large number of processor threads.
82
79
  </p>
83
80
  </p>
84
81
  </div>
@@ -103,6 +100,8 @@ uv add scruby
103
100
 
104
101
  ## Usage
105
102
 
103
+ See more examples here [https://kebasyaty.github.io/scruby/latest/pages/usage/](https://kebasyaty.github.io/scruby/latest/pages/usage/ "Examples").
104
+
106
105
  ```python
107
106
  """Working with keys."""
108
107
 
@@ -115,6 +114,7 @@ from scruby import Scruby, constants
115
114
 
116
115
  constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
117
116
 
117
+
118
118
  class User(BaseModel):
119
119
  """Model of User."""
120
120
  first_name: str
@@ -123,6 +123,7 @@ class User(BaseModel):
123
123
  email: EmailStr
124
124
  phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
125
125
 
126
+
126
127
  async def main() -> None:
127
128
  """Example."""
128
129
  # Get collection of `User`.
@@ -136,7 +137,9 @@ async def main() -> None:
136
137
  phone="+447986123456",
137
138
  )
138
139
 
139
- await user_coll.set_key("+447986123456", user)
140
+ await user_coll.add_key(user.phone, user)
141
+
142
+ await user_coll.update_key(user.phone, user)
140
143
 
141
144
  await user_coll.get_key("+447986123456") # => user
142
145
  await user_coll.get_key("key missing") # => KeyError
@@ -152,12 +155,13 @@ async def main() -> None:
152
155
  # Hint: The main purpose is tests.
153
156
  await Scruby.napalm()
154
157
 
158
+
155
159
  if __name__ == "__main__":
156
160
  anyio.run(main)
157
161
  ```
158
162
 
159
163
  ```python
160
- """Find a single document.
164
+ """Find a single document matching the filter.
161
165
 
162
166
  The search is based on the effect of a quantum loop.
163
167
  The search effectiveness depends on the number of processor threads.
@@ -173,8 +177,9 @@ from scruby import Scruby, constants
173
177
  from pprint import pprint as pp
174
178
 
175
179
  constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
176
- constants.LENGTH_REDUCTION_HASH = 6 # 256 branches in collection
177
- # (main purpose is tests).
180
+ constants.HASH_REDUCE_LEFT = 6 # 256 branches in collection
181
+ # (main purpose is tests).
182
+
178
183
 
179
184
  class User(BaseModel):
180
185
  """Model of User."""
@@ -184,6 +189,7 @@ class User(BaseModel):
184
189
  email: EmailStr
185
190
  phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
186
191
 
192
+
187
193
  async def main() -> None:
188
194
  """Example."""
189
195
  # Get collection of `User`.
@@ -199,7 +205,7 @@ async def main() -> None:
199
205
  )
200
206
 
201
207
  # Add user to collection.
202
- await user_coll.set_key("+447986123456", user)
208
+ await user_coll.add_key(user.phone, user)
203
209
 
204
210
  # Find user by email.
205
211
  user_details: User | None = user_coll.find_one(
@@ -223,12 +229,13 @@ async def main() -> None:
223
229
  # Hint: The main purpose is tests.
224
230
  await Scruby.napalm()
225
231
 
232
+
226
233
  if __name__ == "__main__":
227
234
  anyio.run(main)
228
235
  ```
229
236
 
230
237
  ```python
231
- """Find documents.
238
+ """Find one or more documents matching the filter.
232
239
 
233
240
  The search is based on the effect of a quantum loop.
234
241
  The search effectiveness depends on the number of processor threads.
@@ -244,8 +251,9 @@ from scruby import Scruby, constants
244
251
  from pprint import pprint as pp
245
252
 
246
253
  constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
247
- constants.LENGTH_REDUCTION_HASH = 6 # 256 branches in collection
248
- # (main purpose is tests).
254
+ constants.HASH_REDUCE_LEFT = 6 # 256 branches in collection
255
+ # (main purpose is tests).
256
+
249
257
 
250
258
  class User(BaseModel):
251
259
  """Model of User."""
@@ -255,6 +263,7 @@ class User(BaseModel):
255
263
  email: EmailStr
256
264
  phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
257
265
 
266
+
258
267
  async def main() -> None:
259
268
  """Example."""
260
269
  # Get collection of `User`.
@@ -269,7 +278,7 @@ async def main() -> None:
269
278
  email=f"John_Smith_{num}@gmail.com",
270
279
  phone=f"+44798612345{num}",
271
280
  )
272
- await db.set_key(f"+44798612345{num}", user)
281
+ await user_coll.add_key(user.phone, user)
273
282
 
274
283
  # Find users by email.
275
284
  users: list[User] | None = user_coll.find_many(
@@ -284,41 +293,6 @@ async def main() -> None:
284
293
  # Hint: The main purpose is tests.
285
294
  await Scruby.napalm()
286
295
 
287
- if __name__ == "__main__":
288
- anyio.run(main)
289
- ```
290
-
291
- ```python
292
- """Get collection name."""
293
-
294
- import anyio
295
- import datetime
296
- from typing import Annotated
297
- from pydantic import BaseModel, EmailStr
298
- from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
299
- from scruby import Scruby, constants
300
-
301
- constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
302
-
303
- class User(BaseModel):
304
- """Model of User."""
305
- first_name: str
306
- last_name: str
307
- birthday: datetime.datetime
308
- email: EmailStr
309
- phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
310
-
311
- async def main() -> None:
312
- """Example."""
313
- # Get collection of `User`.
314
- user_coll = Scruby(User)
315
-
316
- print(user_coll.collection_name()) # "User"
317
- print(user_coll.collection_full_name()) # "ScrubyDB/User"
318
-
319
- # Full database deletion.
320
- # Hint: The main purpose is tests.
321
- await Scruby.napalm()
322
296
 
323
297
  if __name__ == "__main__":
324
298
  anyio.run(main)
@@ -0,0 +1,10 @@
1
+ scruby/__init__.py,sha256=elrW_AWMyl3kuTpEqGPaYFSpF8iVzjpivF6MxVNlqoQ,855
2
+ scruby/aggregation.py,sha256=SYGcnMy2eq9vJb-pW3xR9LLAQIQ55TK-LGW_yKQ-7sU,3318
3
+ scruby/constants.py,sha256=KRx7naXDNzT1WVKiYXFJ8uYxS9-aSqoiilsa4qR6y1Y,976
4
+ scruby/db.py,sha256=Ml2A46bOX1P1sF4vKSyEFqklMAjoSpn1lGvj8VCtnSY,26323
5
+ scruby/errors.py,sha256=nMhSLAKo7F3lTB_lgOZ5ksMuBtA1ugHqF8iyp1EY-sY,1042
6
+ scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ scruby-0.17.0.dist-info/METADATA,sha256=8RMszCN_EnAzMTN3wpDrIh8BrrdlxYTX__pLyy6siz8,10079
8
+ scruby-0.17.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
9
+ scruby-0.17.0.dist-info/licenses/LICENSE,sha256=mS0Wz0yGNB63gEcWEnuIb_lldDYV0sjRaO-o_GL6CWE,1074
10
+ scruby-0.17.0.dist-info/RECORD,,
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Gennady Kostyunin
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Gennady Kostyunin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,8 +0,0 @@
1
- scruby/__init__.py,sha256=myX7sG-7oAQZGdgfZtTGXYCCraTeuwi7SjBoltftpnM,648
2
- scruby/constants.py,sha256=GbB-O0qaVdi5EHUp-zRAppFXLR-oHxpXUFVAOCpS0C8,1022
3
- scruby/db.py,sha256=1tfDCwoKwUx0a6DfEOpPAV8NYuifmmrX8Q9gU3K6l58,10407
4
- scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- scruby-0.9.0.dist-info/METADATA,sha256=7Durmb2_VtJ4plz-OM-vhzfLAM8QGYkmVTRX1KFfOYY,11533
6
- scruby-0.9.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- scruby-0.9.0.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
8
- scruby-0.9.0.dist-info/RECORD,,