scruby 0.9.3__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.
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scruby
3
- Version: 0.9.3
4
- Summary: A fast key-value storage library.
5
- Project-URL: Homepage, https://github.com/kebasyaty/scruby
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,10 +17,12 @@ 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
23
24
  Classifier: Programming Language :: Python :: 3.13
25
+ Classifier: Programming Language :: Python :: 3.14
24
26
  Classifier: Programming Language :: Python :: Implementation :: CPython
25
27
  Classifier: Topic :: Database
26
28
  Classifier: Typing :: Typed
@@ -29,7 +31,7 @@ Requires-Dist: anyio>=4.10.0
29
31
  Requires-Dist: orjson>=3.11.3
30
32
  Requires-Dist: phonenumbers>=9.0.13
31
33
  Requires-Dist: pydantic-extra-types>=2.10.5
32
- Requires-Dist: pydantic[email]>=2.11.7
34
+ Requires-Dist: pydantic[email,timezone]>=2.11.7
33
35
  Description-Content-Type: text/markdown
34
36
 
35
37
  <div align="center">
@@ -43,7 +45,7 @@ Description-Content-Type: text/markdown
43
45
  </p>
44
46
  <p>
45
47
  <h1>Scruby</h1>
46
- <h3>A fast key-value storage library.</h3>
48
+ <h3>Asynchronous library for building and managing a hybrid database,<br>by scheme of key-value.</h3>
47
49
  <p align="center">
48
50
  <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
51
  <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 +53,30 @@ Description-Content-Type: text/markdown
51
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>
52
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>
53
55
  <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
- <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>
56
+ <a href="https://pyrefly.org/" alt="Types: Pyrefly"><img src="https://img.shields.io/badge/types-Pyrefly-FFB74D.svg" alt="Types: Pyrefly"></a>
58
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>
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
58
  <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>
59
+ <a href="https://pepy.tech/projects/scruby"><img src="https://static.pepy.tech/badge/scruby" alt="PyPI Downloads"></a>
60
+ <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
61
  </p>
67
62
  <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.
63
+ The library uses fractal-tree addressing and
64
+ <br>
65
+ the search for documents based on the effect of a quantum loop.
66
+ <br>
67
+ The database consists of collections.
68
+ <br>
69
+ The maximum size of the one collection is <b>16**8=4294967296</b> branches,
70
+ <br>
71
+ each branch can store one or more keys.
72
+ <br>
73
+ The value of any key in collection can be obtained maximum in <b>8</b> steps,
74
+ <br>
75
+ thereby achieving high performance.
76
+ <br>
77
+ The effectiveness of the search for documents based on a quantum loop,
78
+ <br>
79
+ requires a large number of processor threads.
82
80
  </p>
83
81
  </p>
84
82
  </div>
@@ -111,24 +109,33 @@ See more examples here [https://kebasyaty.github.io/scruby/latest/pages/usage/](
111
109
  import anyio
112
110
  import datetime
113
111
  from typing import Annotated
114
- from pydantic import BaseModel, EmailStr
112
+ from pydantic import BaseModel, EmailStr, Field
115
113
  from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
116
- from scruby import Scruby, constants
114
+ from scruby import Scruby, settings
117
115
 
118
- constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
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
119
119
 
120
120
  class User(BaseModel):
121
- """Model of User."""
122
- first_name: str
123
- last_name: str
124
- birthday: datetime.datetime
125
- email: EmailStr
126
- 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
+ )
133
+
127
134
 
128
135
  async def main() -> None:
129
136
  """Example."""
130
- # Get collection of `User`.
131
- user_coll = Scruby(User)
137
+ # Get collection `User`.
138
+ user_coll = await Scruby.collection(User)
132
139
 
133
140
  user = User(
134
141
  first_name="John",
@@ -138,7 +145,9 @@ async def main() -> None:
138
145
  phone="+447986123456",
139
146
  )
140
147
 
141
- await user_coll.set_key("+447986123456", user)
148
+ await user_coll.add_doc(user)
149
+
150
+ await user_coll.update_doc(user)
142
151
 
143
152
  await user_coll.get_key("+447986123456") # => user
144
153
  await user_coll.get_key("key missing") # => KeyError
@@ -152,7 +161,8 @@ async def main() -> None:
152
161
 
153
162
  # Full database deletion.
154
163
  # Hint: The main purpose is tests.
155
- await Scruby.napalm()
164
+ Scruby.napalm()
165
+
156
166
 
157
167
  if __name__ == "__main__":
158
168
  anyio.run(main)
@@ -169,61 +179,67 @@ Ideally, hundreds and even thousands of threads are required.
169
179
  import anyio
170
180
  import datetime
171
181
  from typing import Annotated
172
- from pydantic import BaseModel, EmailStr
173
- from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
174
- from scruby import Scruby, constants
182
+ from pydantic import BaseModel, Field
183
+ from scruby import Scruby, settings
175
184
  from pprint import pprint as pp
176
185
 
177
- constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
178
- constants.LENGTH_REDUCTION_HASH = 6 # 256 branches in collection
179
- # (main purpose is tests).
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
+ )
180
203
 
181
- class User(BaseModel):
182
- """Model of User."""
183
- first_name: str
184
- last_name: str
185
- birthday: datetime.datetime
186
- email: EmailStr
187
- phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
188
204
 
189
205
  async def main() -> None:
190
206
  """Example."""
191
- # Get collection of `User`.
192
- user_coll = Scruby(User)
193
-
194
- # Create user.
195
- user = User(
196
- first_name="John",
197
- last_name="Smith",
198
- birthday=datetime.datetime(1970, 1, 1),
199
- email="John_Smith@gmail.com",
200
- 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",
201
216
  )
202
217
 
203
- # Add user to collection.
204
- await user_coll.set_key("+447986123456", user)
218
+ # Add phone to collection.
219
+ await phone_coll.add_doc(phone)
205
220
 
206
- # Find user by email.
207
- user_details: User | None = user_coll.find_one(
208
- filter_fn=lambda doc: doc.email == "John_Smith@gmail.com",
221
+ # Find phone by brand.
222
+ phone_details: Phone | None = await phone_coll.find_one(
223
+ filter_fn=lambda doc: doc.brand == "Samsung",
209
224
  )
210
- if user_details is not None:
211
- pp(user_details)
225
+ if phone_details is not None:
226
+ pp(phone_details)
212
227
  else:
213
- print("No User!")
228
+ print("No Phone!")
214
229
 
215
- # Find user by birthday.
216
- user_details: User | None = user_coll.find_one(
217
- filter_fn=lambda doc: doc.birthday == datetime.datetime(1970, 1, 1),
230
+ # Find phone by model.
231
+ phone_details: Phone | None = await phone_coll.find_one(
232
+ filter_fn=lambda doc: doc.model == "Galaxy A26",
218
233
  )
219
- if user_details is not None:
220
- pp(user_details)
234
+ if phone_details is not None:
235
+ pp(phone_details)
221
236
  else:
222
- print("No User!")
237
+ print("No Phone!")
223
238
 
224
239
  # Full database deletion.
225
240
  # Hint: The main purpose is tests.
226
- await Scruby.napalm()
241
+ Scruby.napalm()
242
+
227
243
 
228
244
  if __name__ == "__main__":
229
245
  anyio.run(main)
@@ -240,51 +256,61 @@ Ideally, hundreds and even thousands of threads are required.
240
256
  import anyio
241
257
  import datetime
242
258
  from typing import Annotated
243
- from pydantic import BaseModel, EmailStr
244
- from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
245
- from scruby import Scruby, constants
259
+ from pydantic import BaseModel, Field
260
+ from scruby import Scruby, settings
246
261
  from pprint import pprint as pp
247
262
 
248
- constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
249
- constants.LENGTH_REDUCTION_HASH = 6 # 256 branches in collection
250
- # (main purpose is tests).
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
+ )
251
280
 
252
- class User(BaseModel):
253
- """Model of User."""
254
- first_name: str
255
- last_name: str
256
- birthday: datetime.datetime
257
- email: EmailStr
258
- phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
259
281
 
260
282
  async def main() -> None:
261
283
  """Example."""
262
- # Get collection of `User`.
263
- user_coll = Scruby(User)
264
-
265
- # Create users.
266
- for num in range(1, 10):
267
- user = User(
268
- first_name="John",
269
- last_name="Smith",
270
- birthday=datetime.datetime(1970, 1, num),
271
- email=f"John_Smith_{num}@gmail.com",
272
- 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,
273
294
  )
274
- await db.set_key(f"+44798612345{num}", user)
295
+ await car_coll.add_doc(car)
275
296
 
276
- # Find users by email.
277
- users: list[User] | None = user_coll.find(
278
- filter_fn=lambda doc: doc.email == "John_Smith_5@gmail.com" or doc.email == "John_Smith_8@gmail.com",
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,
279
300
  )
280
- if users is not None:
281
- pp(users)
301
+ if car_list is not None:
302
+ pp(car_list)
282
303
  else:
283
- print("No users!")
304
+ print("No cars!")
305
+
306
+ # Get collection list.
307
+ collection_list = await Scruby.collection_list()
308
+ print(collection_list) # ["Car"]
284
309
 
285
310
  # Full database deletion.
286
311
  # Hint: The main purpose is tests.
287
- await Scruby.napalm()
312
+ Scruby.napalm()
313
+
288
314
 
289
315
  if __name__ == "__main__":
290
316
  anyio.run(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,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: hatchling 1.28.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -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.
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
- - `LENGTH_REDUCTION_HASH` - 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
- "LENGTH_REDUCTION_HASH",
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
- LENGTH_REDUCTION_HASH: Literal[0, 2, 4, 6] = 0
@@ -1,8 +0,0 @@
1
- scruby/__init__.py,sha256=wFwUS1KcLxfIopXOVS8gPue9fNzIIU2cVj_RgK5drz4,849
2
- scruby/constants.py,sha256=GbB-O0qaVdi5EHUp-zRAppFXLR-oHxpXUFVAOCpS0C8,1022
3
- scruby/db.py,sha256=reYCZduh4GAycS17oPw8BWoFd-M9A8N7BW_uPFwUd_w,10941
4
- scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- scruby-0.9.3.dist-info/METADATA,sha256=YBlk8IR3bDVRV-XKLKEHkpd3Bir97OF0wyOe0jFDpR0,10828
6
- scruby-0.9.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- scruby-0.9.3.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
8
- scruby-0.9.3.dist-info/RECORD,,