scruby 0.17.0__py3-none-any.whl → 0.27.2__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/__init__.py +17 -9
- scruby/aggregation.py +4 -0
- scruby/db.py +100 -643
- scruby/errors.py +8 -2
- scruby/mixins/__init__.py +25 -0
- scruby/mixins/collection.py +50 -0
- scruby/mixins/count.py +62 -0
- scruby/mixins/custom_task.py +75 -0
- scruby/mixins/delete.py +96 -0
- scruby/mixins/docs.py +168 -0
- scruby/mixins/find.py +149 -0
- scruby/mixins/update.py +99 -0
- scruby/settings.py +44 -0
- {scruby-0.17.0.dist-info → scruby-0.27.2.dist-info}/METADATA +114 -96
- scruby-0.27.2.dist-info/RECORD +18 -0
- {scruby-0.17.0.dist-info → scruby-0.27.2.dist-info}/WHEEL +1 -1
- scruby/constants.py +0 -31
- scruby-0.17.0.dist-info/RECORD +0 -10
- {scruby-0.17.0.dist-info → scruby-0.27.2.dist-info}/licenses/LICENSE +0 -0
scruby/mixins/update.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Scruby - Asynchronous library for building and managing a hybrid database, by scheme of key-value.
|
|
2
|
+
# Copyright (c) 2025 Gennady Kostyunin
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
"""Methods for updating documents."""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
__all__ = ("Update",)
|
|
10
|
+
|
|
11
|
+
import concurrent.futures
|
|
12
|
+
from collections.abc import Callable
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import orjson
|
|
16
|
+
from anyio import Path
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Update:
|
|
20
|
+
"""Methods for updating documents."""
|
|
21
|
+
|
|
22
|
+
@staticmethod
|
|
23
|
+
async def _task_update(
|
|
24
|
+
branch_number: int,
|
|
25
|
+
filter_fn: Callable,
|
|
26
|
+
hash_reduce_left: str,
|
|
27
|
+
db_root: str,
|
|
28
|
+
class_model: Any,
|
|
29
|
+
new_data: dict[str, Any],
|
|
30
|
+
) -> int:
|
|
31
|
+
"""Task for find documents.
|
|
32
|
+
|
|
33
|
+
This method is for internal use.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
The number of updated documents.
|
|
37
|
+
"""
|
|
38
|
+
branch_number_as_hash: str = f"{branch_number:08x}"[hash_reduce_left:]
|
|
39
|
+
separated_hash: str = "/".join(list(branch_number_as_hash))
|
|
40
|
+
leaf_path: Path = Path(
|
|
41
|
+
*(
|
|
42
|
+
db_root,
|
|
43
|
+
class_model.__name__,
|
|
44
|
+
separated_hash,
|
|
45
|
+
"leaf.json",
|
|
46
|
+
),
|
|
47
|
+
)
|
|
48
|
+
counter: int = 0
|
|
49
|
+
if await leaf_path.exists():
|
|
50
|
+
data_json: bytes = await leaf_path.read_bytes()
|
|
51
|
+
data: dict[str, str] = orjson.loads(data_json) or {}
|
|
52
|
+
new_state: dict[str, str] = {}
|
|
53
|
+
for _, val in data.items():
|
|
54
|
+
doc = class_model.model_validate_json(val)
|
|
55
|
+
if filter_fn(doc):
|
|
56
|
+
for key, value in new_data.items():
|
|
57
|
+
doc.__dict__[key] = value
|
|
58
|
+
new_state[key] = doc.model_dump_json()
|
|
59
|
+
counter += 1
|
|
60
|
+
await leaf_path.write_bytes(orjson.dumps(new_state))
|
|
61
|
+
return counter
|
|
62
|
+
|
|
63
|
+
async def update_many(
|
|
64
|
+
self,
|
|
65
|
+
filter_fn: Callable,
|
|
66
|
+
new_data: dict[str, Any],
|
|
67
|
+
) -> int:
|
|
68
|
+
"""Updates one or more documents matching the filter.
|
|
69
|
+
|
|
70
|
+
The search is based on the effect of a quantum loop.
|
|
71
|
+
The search effectiveness depends on the number of processor threads.
|
|
72
|
+
Ideally, hundreds and even thousands of threads are required.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
filter_fn: A function that execute the conditions of filtering.
|
|
76
|
+
new_data: New data for the fields that need to be updated.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
The number of updated documents.
|
|
80
|
+
"""
|
|
81
|
+
branch_numbers: range = range(1, self._max_branch_number)
|
|
82
|
+
update_task_fn: Callable = self._task_update
|
|
83
|
+
hash_reduce_left: int = self._hash_reduce_left
|
|
84
|
+
db_root: str = self._db_root
|
|
85
|
+
class_model: Any = self._class_model
|
|
86
|
+
counter: int = 0
|
|
87
|
+
with concurrent.futures.ThreadPoolExecutor(self._max_workers) as executor:
|
|
88
|
+
for branch_number in branch_numbers:
|
|
89
|
+
future = executor.submit(
|
|
90
|
+
update_task_fn,
|
|
91
|
+
branch_number,
|
|
92
|
+
filter_fn,
|
|
93
|
+
hash_reduce_left,
|
|
94
|
+
db_root,
|
|
95
|
+
class_model,
|
|
96
|
+
new_data,
|
|
97
|
+
)
|
|
98
|
+
counter += await future.result()
|
|
99
|
+
return counter
|
scruby/settings.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Scruby - Asynchronous library for building and managing a hybrid database, by scheme of key-value.
|
|
2
|
+
# Copyright (c) 2025 Gennady Kostyunin
|
|
3
|
+
# SPDX-License-Identifier: MIT
|
|
4
|
+
#
|
|
5
|
+
"""Database settings.
|
|
6
|
+
|
|
7
|
+
The module contains the following parameters:
|
|
8
|
+
|
|
9
|
+
- `DB_ROOT` - Path to root directory of database. `By default = "ScrubyDB" (in root of project)`.
|
|
10
|
+
- `HASH_REDUCE_LEFT` - The length of the hash reduction on the left side.
|
|
11
|
+
- `0` - 4294967296 branches in collection.
|
|
12
|
+
- `2` - 16777216 branches in collection.
|
|
13
|
+
- `4` - 65536 branches in collection.
|
|
14
|
+
- `6` - 256 branches in collection (by default).
|
|
15
|
+
- `MAX_WORKERS` - The maximum number of processes that can be used `By default = None`.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
__all__ = (
|
|
21
|
+
"DB_ROOT",
|
|
22
|
+
"HASH_REDUCE_LEFT",
|
|
23
|
+
"MAX_WORKERS",
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from typing import Literal
|
|
27
|
+
|
|
28
|
+
# Path to root directory of database
|
|
29
|
+
# By default = "ScrubyDB" (in root of project).
|
|
30
|
+
DB_ROOT: str = "ScrubyDB"
|
|
31
|
+
|
|
32
|
+
# The length of the hash reduction on the left side.
|
|
33
|
+
# 0 = 4294967296 branches in collection.
|
|
34
|
+
# 2 = 16777216 branches in collection.
|
|
35
|
+
# 4 = 65536 branches in collection.
|
|
36
|
+
# 6 = 256 branches in collection (by default).
|
|
37
|
+
# Number of branches is number of requests to the hard disk during quantum operations.
|
|
38
|
+
# Quantum operations: find_one, find_many, count_documents, delete_many, run_custom_task.
|
|
39
|
+
HASH_REDUCE_LEFT: Literal[0, 2, 4, 6] = 6
|
|
40
|
+
|
|
41
|
+
# The maximum number of processes that can be used to execute the given calls.
|
|
42
|
+
# If None, then as many worker processes will be
|
|
43
|
+
# created as the machine has processors.
|
|
44
|
+
MAX_WORKERS: int | None = None
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: scruby
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary:
|
|
5
|
-
Project-URL: Homepage, https://github.
|
|
3
|
+
Version: 0.27.2
|
|
4
|
+
Summary: Asynchronous library for building and managing a hybrid database, by scheme of key-value.
|
|
5
|
+
Project-URL: Homepage, https://kebasyaty.github.io/scruby/
|
|
6
6
|
Project-URL: Repository, https://github.com/kebasyaty/scruby
|
|
7
7
|
Project-URL: Source, https://github.com/kebasyaty/scruby
|
|
8
8
|
Project-URL: Bug Tracker, https://github.com/kebasyaty/scruby/issues
|
|
@@ -17,6 +17,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
17
17
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
18
18
|
Classifier: Operating System :: Microsoft :: Windows
|
|
19
19
|
Classifier: Operating System :: POSIX
|
|
20
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
20
21
|
Classifier: Programming Language :: Python :: 3
|
|
21
22
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
23
|
Classifier: Programming Language :: Python :: 3.12
|
|
@@ -30,7 +31,7 @@ Requires-Dist: anyio>=4.10.0
|
|
|
30
31
|
Requires-Dist: orjson>=3.11.3
|
|
31
32
|
Requires-Dist: phonenumbers>=9.0.13
|
|
32
33
|
Requires-Dist: pydantic-extra-types>=2.10.5
|
|
33
|
-
Requires-Dist: pydantic[email]>=2.11.7
|
|
34
|
+
Requires-Dist: pydantic[email,timezone]>=2.11.7
|
|
34
35
|
Description-Content-Type: text/markdown
|
|
35
36
|
|
|
36
37
|
<div align="center">
|
|
@@ -52,7 +53,7 @@ Description-Content-Type: text/markdown
|
|
|
52
53
|
<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>
|
|
53
54
|
<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>
|
|
54
55
|
<br>
|
|
55
|
-
<a href="https://
|
|
56
|
+
<a href="https://pyrefly.org/" alt="Types: Pyrefly"><img src="https://img.shields.io/badge/types-Pyrefly-FFB74D.svg" alt="Types: Pyrefly"></a>
|
|
56
57
|
<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>
|
|
57
58
|
<a href="https://pypi.org/project/scruby"><img src="https://img.shields.io/pypi/format/scruby" alt="Format"></a>
|
|
58
59
|
<a href="https://pepy.tech/projects/scruby"><img src="https://static.pepy.tech/badge/scruby" alt="PyPI Downloads"></a>
|
|
@@ -65,11 +66,11 @@ Description-Content-Type: text/markdown
|
|
|
65
66
|
<br>
|
|
66
67
|
The database consists of collections.
|
|
67
68
|
<br>
|
|
68
|
-
The maximum size of the one collection is 16
|
|
69
|
+
The maximum size of the one collection is <b>16**8=4294967296</b> branches,
|
|
69
70
|
<br>
|
|
70
71
|
each branch can store one or more keys.
|
|
71
72
|
<br>
|
|
72
|
-
The value of any key in collection can be obtained in 8 steps,
|
|
73
|
+
The value of any key in collection can be obtained maximum in <b>8</b> steps,
|
|
73
74
|
<br>
|
|
74
75
|
thereby achieving high performance.
|
|
75
76
|
<br>
|
|
@@ -108,26 +109,33 @@ See more examples here [https://kebasyaty.github.io/scruby/latest/pages/usage/](
|
|
|
108
109
|
import anyio
|
|
109
110
|
import datetime
|
|
110
111
|
from typing import Annotated
|
|
111
|
-
from pydantic import BaseModel, EmailStr
|
|
112
|
+
from pydantic import BaseModel, EmailStr, Field
|
|
112
113
|
from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
|
|
113
|
-
from scruby import Scruby,
|
|
114
|
-
|
|
115
|
-
constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
|
|
114
|
+
from scruby import Scruby, settings
|
|
116
115
|
|
|
116
|
+
settings.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
|
|
117
|
+
settings.HASH_REDUCE_LEFT = 6 # By default = 6
|
|
118
|
+
settings.MAX_WORKERS = None # By default = None
|
|
117
119
|
|
|
118
120
|
class User(BaseModel):
|
|
119
|
-
"""
|
|
120
|
-
first_name: str
|
|
121
|
-
last_name: str
|
|
122
|
-
birthday: datetime.datetime
|
|
123
|
-
email: EmailStr
|
|
124
|
-
phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
|
|
121
|
+
"""User model."""
|
|
122
|
+
first_name: str = Field(strict=True)
|
|
123
|
+
last_name: str = Field(strict=True)
|
|
124
|
+
birthday: datetime.datetime = Field(strict=True)
|
|
125
|
+
email: EmailStr = Field(strict=True)
|
|
126
|
+
phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")] = Field(frozen=True)
|
|
127
|
+
# The key is always at the bottom
|
|
128
|
+
key: str = Field(
|
|
129
|
+
strict=True,
|
|
130
|
+
frozen=True,
|
|
131
|
+
default_factory=lambda data: data["phone"],
|
|
132
|
+
)
|
|
125
133
|
|
|
126
134
|
|
|
127
135
|
async def main() -> None:
|
|
128
136
|
"""Example."""
|
|
129
|
-
# Get collection
|
|
130
|
-
user_coll = Scruby(User)
|
|
137
|
+
# Get collection `User`.
|
|
138
|
+
user_coll = await Scruby.collection(User)
|
|
131
139
|
|
|
132
140
|
user = User(
|
|
133
141
|
first_name="John",
|
|
@@ -137,9 +145,9 @@ async def main() -> None:
|
|
|
137
145
|
phone="+447986123456",
|
|
138
146
|
)
|
|
139
147
|
|
|
140
|
-
await user_coll.
|
|
148
|
+
await user_coll.add_doc(user)
|
|
141
149
|
|
|
142
|
-
await user_coll.
|
|
150
|
+
await user_coll.update_doc(user)
|
|
143
151
|
|
|
144
152
|
await user_coll.get_key("+447986123456") # => user
|
|
145
153
|
await user_coll.get_key("key missing") # => KeyError
|
|
@@ -153,7 +161,7 @@ async def main() -> None:
|
|
|
153
161
|
|
|
154
162
|
# Full database deletion.
|
|
155
163
|
# Hint: The main purpose is tests.
|
|
156
|
-
|
|
164
|
+
Scruby.napalm()
|
|
157
165
|
|
|
158
166
|
|
|
159
167
|
if __name__ == "__main__":
|
|
@@ -171,63 +179,66 @@ Ideally, hundreds and even thousands of threads are required.
|
|
|
171
179
|
import anyio
|
|
172
180
|
import datetime
|
|
173
181
|
from typing import Annotated
|
|
174
|
-
from pydantic import BaseModel,
|
|
175
|
-
from
|
|
176
|
-
from scruby import Scruby, constants
|
|
182
|
+
from pydantic import BaseModel, Field
|
|
183
|
+
from scruby import Scruby, settings
|
|
177
184
|
from pprint import pprint as pp
|
|
178
185
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
class
|
|
185
|
-
"""
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
186
|
+
settings.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
|
|
187
|
+
settings.HASH_REDUCE_LEFT = 6 # By default = 6
|
|
188
|
+
settings.MAX_WORKERS = None # By default = None
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Phone(BaseModel):
|
|
192
|
+
"""Phone model."""
|
|
193
|
+
brand: str = Field(strict=True, frozen=True)
|
|
194
|
+
model: str = Field(strict=True, frozen=True)
|
|
195
|
+
screen_diagonal: float = Field(strict=True)
|
|
196
|
+
matrix_type: str = Field(strict=True)
|
|
197
|
+
# The key is always at the bottom
|
|
198
|
+
key: str = Field(
|
|
199
|
+
strict=True,
|
|
200
|
+
frozen=True,
|
|
201
|
+
default_factory=lambda data: f"{data['brand']}:{data['model']}",
|
|
202
|
+
)
|
|
191
203
|
|
|
192
204
|
|
|
193
205
|
async def main() -> None:
|
|
194
206
|
"""Example."""
|
|
195
|
-
# Get collection
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
# Create
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
phone="+447986123456",
|
|
207
|
+
# Get collection `Phone`.
|
|
208
|
+
phone_coll = await Scruby.collection(Phone)
|
|
209
|
+
|
|
210
|
+
# Create phone.
|
|
211
|
+
phone = Phone(
|
|
212
|
+
brand="Samsung",
|
|
213
|
+
model="Galaxy A26",
|
|
214
|
+
screen_diagonal=6.7,
|
|
215
|
+
matrix_type="Super AMOLED",
|
|
205
216
|
)
|
|
206
217
|
|
|
207
|
-
# Add
|
|
208
|
-
await
|
|
218
|
+
# Add phone to collection.
|
|
219
|
+
await phone_coll.add_doc(phone)
|
|
209
220
|
|
|
210
|
-
# Find
|
|
211
|
-
|
|
212
|
-
filter_fn=lambda doc: doc.
|
|
221
|
+
# Find phone by brand.
|
|
222
|
+
phone_details: Phone | None = await phone_coll.find_one(
|
|
223
|
+
filter_fn=lambda doc: doc.brand == "Samsung",
|
|
213
224
|
)
|
|
214
|
-
if
|
|
215
|
-
pp(
|
|
225
|
+
if phone_details is not None:
|
|
226
|
+
pp(phone_details)
|
|
216
227
|
else:
|
|
217
|
-
print("No
|
|
228
|
+
print("No Phone!")
|
|
218
229
|
|
|
219
|
-
# Find
|
|
220
|
-
|
|
221
|
-
filter_fn=lambda doc: doc.
|
|
230
|
+
# Find phone by model.
|
|
231
|
+
phone_details: Phone | None = await phone_coll.find_one(
|
|
232
|
+
filter_fn=lambda doc: doc.model == "Galaxy A26",
|
|
222
233
|
)
|
|
223
|
-
if
|
|
224
|
-
pp(
|
|
234
|
+
if phone_details is not None:
|
|
235
|
+
pp(phone_details)
|
|
225
236
|
else:
|
|
226
|
-
print("No
|
|
237
|
+
print("No Phone!")
|
|
227
238
|
|
|
228
239
|
# Full database deletion.
|
|
229
240
|
# Hint: The main purpose is tests.
|
|
230
|
-
|
|
241
|
+
Scruby.napalm()
|
|
231
242
|
|
|
232
243
|
|
|
233
244
|
if __name__ == "__main__":
|
|
@@ -245,53 +256,60 @@ Ideally, hundreds and even thousands of threads are required.
|
|
|
245
256
|
import anyio
|
|
246
257
|
import datetime
|
|
247
258
|
from typing import Annotated
|
|
248
|
-
from pydantic import BaseModel,
|
|
249
|
-
from
|
|
250
|
-
from scruby import Scruby, constants
|
|
259
|
+
from pydantic import BaseModel, Field
|
|
260
|
+
from scruby import Scruby, settings
|
|
251
261
|
from pprint import pprint as pp
|
|
252
262
|
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
class
|
|
259
|
-
"""
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
263
|
+
settings.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
|
|
264
|
+
settings.HASH_REDUCE_LEFT = 6 # By default = 6
|
|
265
|
+
settings.MAX_WORKERS = None # By default = None
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
class Car(BaseModel):
|
|
269
|
+
"""Car model."""
|
|
270
|
+
brand: str = Field(strict=True, frozen=True)
|
|
271
|
+
model: str = Field(strict=True, frozen=True)
|
|
272
|
+
year: int = Field(strict=True)
|
|
273
|
+
power_reserve: int = Field(strict=True)
|
|
274
|
+
# The key is always at the bottom
|
|
275
|
+
key: str = Field(
|
|
276
|
+
strict=True,
|
|
277
|
+
frozen=True,
|
|
278
|
+
default_factory=lambda data: f"{data['brand']}:{data['model']}",
|
|
279
|
+
)
|
|
265
280
|
|
|
266
281
|
|
|
267
282
|
async def main() -> None:
|
|
268
283
|
"""Example."""
|
|
269
|
-
# Get collection
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
# Create
|
|
273
|
-
for
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
phone=f"+44798612345{num}",
|
|
284
|
+
# Get collection `Car`.
|
|
285
|
+
car_coll = await Scruby.collection(Car)
|
|
286
|
+
|
|
287
|
+
# Create cars.
|
|
288
|
+
for name in range(1, 10):
|
|
289
|
+
car = Car(
|
|
290
|
+
brand="Mazda",
|
|
291
|
+
model=f"EZ-6 {num}",
|
|
292
|
+
year=2025,
|
|
293
|
+
power_reserve=600,
|
|
280
294
|
)
|
|
281
|
-
await
|
|
295
|
+
await car_coll.add_doc(car)
|
|
282
296
|
|
|
283
|
-
# Find
|
|
284
|
-
|
|
285
|
-
filter_fn=lambda doc: doc.
|
|
297
|
+
# Find cars by brand and year.
|
|
298
|
+
car_list: list[Car] | None = await car_coll.find_many(
|
|
299
|
+
filter_fn=lambda doc: doc.brand == "Mazda" and doc.year == 2025,
|
|
286
300
|
)
|
|
287
|
-
if
|
|
288
|
-
pp(
|
|
301
|
+
if car_list is not None:
|
|
302
|
+
pp(car_list)
|
|
289
303
|
else:
|
|
290
|
-
print("No
|
|
304
|
+
print("No cars!")
|
|
305
|
+
|
|
306
|
+
# Get collection list.
|
|
307
|
+
collection_list = await Scruby.collection_list()
|
|
308
|
+
print(collection_list) # ["Car"]
|
|
291
309
|
|
|
292
310
|
# Full database deletion.
|
|
293
311
|
# Hint: The main purpose is tests.
|
|
294
|
-
|
|
312
|
+
Scruby.napalm()
|
|
295
313
|
|
|
296
314
|
|
|
297
315
|
if __name__ == "__main__":
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
scruby/__init__.py,sha256=IVQbFk2jKaRnHJQys_CcYXw3bvmN4igWFAQmzLxE1k0,1283
|
|
2
|
+
scruby/aggregation.py,sha256=bd70J1Xye6faNHD8LS3lVQoHWKtPdPV_cqT_i7oui38,3491
|
|
3
|
+
scruby/db.py,sha256=djo4JkfuKCcV3jRbd2L3mIwENS3ptqJBt7SlAuiRhGY,6794
|
|
4
|
+
scruby/errors.py,sha256=D0jisudUsZk9iXp4nRSymaSMwyqHPVshsSlxx4HDVVk,1297
|
|
5
|
+
scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
scruby/settings.py,sha256=_uVdZIGWoi6q9zcu0c2PS51OBEBNASRRrxfzaF7Nwy0,1580
|
|
7
|
+
scruby/mixins/__init__.py,sha256=jmRJHs1fcSIIFm-yz2fq81-dC3not3EW9lKzLe1Yr64,627
|
|
8
|
+
scruby/mixins/collection.py,sha256=coF-IOhicV_EihDwnYf6SW5Mfi3nOFR0gAhCc619NmI,1382
|
|
9
|
+
scruby/mixins/count.py,sha256=OyRznB7AfZcSka3uFy2miMMOt85aUmiJN1RjJlQOTPI,2059
|
|
10
|
+
scruby/mixins/custom_task.py,sha256=BcSJfd0eUiyQ6RgTOSsTbJZvQ5ggXtp2YueXwPWgcd8,2386
|
|
11
|
+
scruby/mixins/delete.py,sha256=f3xkaMOR6wBqfjee1NCcw98fU8imZRMhSjucrxFcbFU,3055
|
|
12
|
+
scruby/mixins/docs.py,sha256=OUByWbHfNVWJVkUrhCsJZdVqf0zez_an6Gti2n5iKnM,5671
|
|
13
|
+
scruby/mixins/find.py,sha256=T2MzbP_vinf5qaLm4iR5T3iMFbMQNkUbQPRx2C5e20E,5373
|
|
14
|
+
scruby/mixins/update.py,sha256=oAfOxIPHl3ro8Vpjnzrdj8PSzIz5dIQO_AWSni5878Y,3238
|
|
15
|
+
scruby-0.27.2.dist-info/METADATA,sha256=Ua5HIieo3iv00SOez0jFMjiC7G324ZtY20FH76x_Xgw,10659
|
|
16
|
+
scruby-0.27.2.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
17
|
+
scruby-0.27.2.dist-info/licenses/LICENSE,sha256=mS0Wz0yGNB63gEcWEnuIb_lldDYV0sjRaO-o_GL6CWE,1074
|
|
18
|
+
scruby-0.27.2.dist-info/RECORD,,
|
scruby/constants.py
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
"""Constant variables.
|
|
2
|
-
|
|
3
|
-
The module contains the following variables:
|
|
4
|
-
|
|
5
|
-
- `DB_ROOT` - Path to root directory of database. `By default = "ScrubyDB"` (*in root of project*).
|
|
6
|
-
- `HASH_REDUCE_LEFT` - The length of the hash reduction on the left side.
|
|
7
|
-
- `0` - 4294967296 branches in collection (by default).
|
|
8
|
-
- `2` - 16777216 branches in collectionю
|
|
9
|
-
- `4` - 65536 branches in collectionю
|
|
10
|
-
- `6` - 256 branches in collection (main purpose is tests).
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from __future__ import annotations
|
|
14
|
-
|
|
15
|
-
__all__ = (
|
|
16
|
-
"DB_ROOT",
|
|
17
|
-
"HASH_REDUCE_LEFT",
|
|
18
|
-
)
|
|
19
|
-
|
|
20
|
-
from typing import Literal
|
|
21
|
-
|
|
22
|
-
# Path to root directory of database
|
|
23
|
-
# By default = "ScrubyDB" (in root of project).
|
|
24
|
-
DB_ROOT: str = "ScrubyDB"
|
|
25
|
-
|
|
26
|
-
# The length of the hash reduction on the left side.
|
|
27
|
-
# 0 = 4294967296 branches in collection (by default).
|
|
28
|
-
# 2 = 16777216 branches in collectionю
|
|
29
|
-
# 4 = 65536 branches in collectionю
|
|
30
|
-
# 6 = 256 branches in collection (main purpose is tests).
|
|
31
|
-
HASH_REDUCE_LEFT: Literal[0, 2, 4, 6] = 0
|
scruby-0.17.0.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
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,,
|
|
File without changes
|