scruby 0.7.2__py3-none-any.whl → 0.8.1__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/db.py CHANGED
@@ -229,7 +229,54 @@ class Scruby[T]:
229
229
  db_root,
230
230
  class_model,
231
231
  )
232
- result = future.result(timeout)
233
- if result is not None:
234
- return result
232
+ doc = future.result(timeout)
233
+ if doc is not None:
234
+ return doc
235
235
  return None
236
+
237
+ def find_many(
238
+ self,
239
+ filter_fn: Callable,
240
+ db_query_docs_limit: int = 1000,
241
+ max_workers: int | None = None,
242
+ timeout: float | None = None,
243
+ ) -> list[T] | None:
244
+ """Find documents.
245
+
246
+ The search is based on the effect of a quantum loop.
247
+ The search effectiveness depends on the number of processor threads.
248
+ Ideally, hundreds and even thousands of threads are required.
249
+
250
+ Args:
251
+ filter_fn: A function that execute the conditions of filtering.
252
+ db_query_docs_limit: Limiting the number of request results. By default = 1000.
253
+ max_workers: The maximum number of processes that can be used to
254
+ execute the given calls. If None or not given then as many
255
+ worker processes will be created as the machine has processors.
256
+ timeout: The number of seconds to wait for the result if the future isn't done.
257
+ If None, then there is no limit on the wait time.
258
+ """
259
+ keys: range = range(1, self.__max_num_keys)
260
+ search_task_fn: Callable = self.search_task
261
+ length_reduction_hash: int = self.__length_reduction_hash
262
+ db_root: str = self.__db_root
263
+ class_model: T = self.__class_model
264
+ counter: int = 0
265
+ with concurrent.futures.ThreadPoolExecutor(max_workers) as executor:
266
+ results = []
267
+ for key in keys:
268
+ if counter == db_query_docs_limit:
269
+ break
270
+ future = executor.submit(
271
+ search_task_fn,
272
+ key,
273
+ filter_fn,
274
+ length_reduction_hash,
275
+ db_root,
276
+ class_model,
277
+ )
278
+ doc = future.result(timeout)
279
+ if doc is not None:
280
+ results.append(doc)
281
+ counter += 1
282
+ return results or None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scruby
3
- Version: 0.7.2
3
+ Version: 0.8.1
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,8 +108,9 @@ uv add scruby
108
108
 
109
109
  import anyio
110
110
  import datetime
111
+ from typing import Annotated
111
112
  from pydantic import BaseModel, EmailStr
112
- from pydantic_extra_types.phone_numbers import PhoneNumber
113
+ from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
113
114
  from scruby import Scruby, constants
114
115
 
115
116
  constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
@@ -120,7 +121,7 @@ class User(BaseModel):
120
121
  last_name: str
121
122
  birthday: datetime.datetime
122
123
  email: EmailStr
123
- phone: PhoneNumber
124
+ phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
124
125
 
125
126
  async def main() -> None:
126
127
  """Example."""
@@ -165,8 +166,9 @@ Ideally, hundreds and even thousands of threads are required.
165
166
 
166
167
  import anyio
167
168
  import datetime
169
+ from typing import Annotated
168
170
  from pydantic import BaseModel, EmailStr
169
- from pydantic_extra_types.phone_numbers import PhoneNumber
171
+ from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
170
172
  from scruby import Scruby, constants
171
173
  from pprint import pprint as pp
172
174
 
@@ -180,7 +182,7 @@ class User(BaseModel):
180
182
  last_name: str
181
183
  birthday: datetime.datetime
182
184
  email: EmailStr
183
- phone: PhoneNumber
185
+ phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
184
186
 
185
187
  async def main() -> None:
186
188
  """Example."""
@@ -225,6 +227,67 @@ if __name__ == "__main__":
225
227
  anyio.run(main)
226
228
  ```
227
229
 
230
+ ```python
231
+ """Find documents.
232
+
233
+ The search is based on the effect of a quantum loop.
234
+ The search effectiveness depends on the number of processor threads.
235
+ Ideally, hundreds and even thousands of threads are required.
236
+ """
237
+
238
+ import anyio
239
+ import datetime
240
+ from typing import Annotated
241
+ from pydantic import BaseModel, EmailStr
242
+ from pydantic_extra_types.phone_numbers import PhoneNumber, PhoneNumberValidator
243
+ from scruby import Scruby, constants
244
+ from pprint import pprint as pp
245
+
246
+ constants.DB_ROOT = "ScrubyDB" # By default = "ScrubyDB"
247
+ constants.LENGTH_REDUCTION_HASH = 6 # 256 branches in collection
248
+ # (main purpose is tests).
249
+
250
+ class User(BaseModel):
251
+ """Model of User."""
252
+ first_name: str
253
+ last_name: str
254
+ birthday: datetime.datetime
255
+ email: EmailStr
256
+ phone: Annotated[PhoneNumber, PhoneNumberValidator(number_format="E164")]
257
+
258
+ async def main() -> None:
259
+ """Example."""
260
+ # Get collection of `User`.
261
+ user_coll = Scruby(User)
262
+
263
+ # Create users.
264
+ for num in range(1, 10):
265
+ user = User(
266
+ first_name="John",
267
+ last_name="Smith",
268
+ birthday=datetime.datetime(1970, 1, num),
269
+ email=f"John_Smith_{num}@gmail.com",
270
+ phone=f"+44798612345{num}",
271
+ )
272
+ await db.set_key(f"+44798612345{num}", user)
273
+
274
+ # Find users by email.
275
+ users: list[User] | None = user_coll.find_many(
276
+ filter_fn=lambda doc: doc.email == "John_Smith_5@gmail.com" or doc.email == "John_Smith_8@gmail.com",
277
+ )
278
+ if users is not None:
279
+ pp(users)
280
+ else:
281
+ print("No users!")
282
+
283
+ # Full database deletion.
284
+ # Hint: The main purpose is tests.
285
+ await Scruby.napalm()
286
+
287
+ if __name__ == "__main__":
288
+ anyio.run(main)
289
+ ```
290
+
228
291
  ## Changelog
229
292
 
230
293
  [View the change history](https://github.com/kebasyaty/scruby/blob/v0/CHANGELOG.md "Changelog").
@@ -0,0 +1,8 @@
1
+ scruby/__init__.py,sha256=myX7sG-7oAQZGdgfZtTGXYCCraTeuwi7SjBoltftpnM,648
2
+ scruby/constants.py,sha256=GbB-O0qaVdi5EHUp-zRAppFXLR-oHxpXUFVAOCpS0C8,1022
3
+ scruby/db.py,sha256=FWCrcpzP93V1fk7NXhp6x2UgGkwqvk7qXvphm38R0X8,10130
4
+ scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ scruby-0.8.1.dist-info/METADATA,sha256=TpqA2Ukl-TnolmTr-mRTRIFGE2KcKdzm8tLP1xRWKFM,10632
6
+ scruby-0.8.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ scruby-0.8.1.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
8
+ scruby-0.8.1.dist-info/RECORD,,
@@ -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=84DRrw21jiAmEsxjOOJnAfFvfE8hNdaJ-TB9BQtM0CQ,8114
4
- scruby/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
- scruby-0.7.2.dist-info/METADATA,sha256=b_02kOWP7dScGNwKtvVwQrv7CPiIHHIJ33OxMMz5Ink,8673
6
- scruby-0.7.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- scruby-0.7.2.dist-info/licenses/LICENSE,sha256=2zZINd6m_jNYlowdQImlEizyhSui5cBAJZRhWQURcEc,1095
8
- scruby-0.7.2.dist-info/RECORD,,
File without changes