kover 2.7.0__tar.gz → 2.7.2__tar.gz

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.
Files changed (62) hide show
  1. {kover-2.7.0 → kover-2.7.2}/.gitignore +2 -3
  2. {kover-2.7.0 → kover-2.7.2}/PKG-INFO +2 -2
  3. {kover-2.7.0 → kover-2.7.2}/README.md +1 -1
  4. {kover-2.7.0 → kover-2.7.2}/kover/__init__.py +3 -1
  5. kover-2.7.2/kover/bulk_write_builder.py +104 -0
  6. {kover-2.7.0 → kover-2.7.2}/kover/client.py +12 -0
  7. {kover-2.7.0 → kover-2.7.2}/kover/database.py +1 -1
  8. {kover-2.7.0 → kover-2.7.2}/kover/models/operations.py +33 -5
  9. {kover-2.7.0 → kover-2.7.2}/kover/network/transport.py +5 -5
  10. {kover-2.7.0 → kover-2.7.2}/kover/schema.py +3 -3
  11. {kover-2.7.0 → kover-2.7.2}/kover/transaction.py +3 -1
  12. {kover-2.7.0 → kover-2.7.2}/pyproject.toml +1 -1
  13. {kover-2.7.0 → kover-2.7.2}/CODE_OF_CONDUCT.md +0 -0
  14. {kover-2.7.0 → kover-2.7.2}/LICENSE +0 -0
  15. {kover-2.7.0 → kover-2.7.2}/kover/_internals/__init__.py +0 -0
  16. {kover-2.7.0 → kover-2.7.2}/kover/_internals/_mixins.py +0 -0
  17. {kover-2.7.0 → kover-2.7.2}/kover/_internals/_serializers.py +0 -0
  18. {kover-2.7.0 → kover-2.7.2}/kover/bson/__init__.py +0 -0
  19. {kover-2.7.0 → kover-2.7.2}/kover/bson/_helpers.py +0 -0
  20. {kover-2.7.0 → kover-2.7.2}/kover/bson/binary.py +0 -0
  21. {kover-2.7.0 → kover-2.7.2}/kover/bson/code.py +0 -0
  22. {kover-2.7.0 → kover-2.7.2}/kover/bson/codec_options.py +0 -0
  23. {kover-2.7.0 → kover-2.7.2}/kover/bson/datetime_ms.py +0 -0
  24. {kover-2.7.0 → kover-2.7.2}/kover/bson/dbref.py +0 -0
  25. {kover-2.7.0 → kover-2.7.2}/kover/bson/decimal128.py +0 -0
  26. {kover-2.7.0 → kover-2.7.2}/kover/bson/errors.py +0 -0
  27. {kover-2.7.0 → kover-2.7.2}/kover/bson/int64.py +0 -0
  28. {kover-2.7.0 → kover-2.7.2}/kover/bson/json_util.py +0 -0
  29. {kover-2.7.0 → kover-2.7.2}/kover/bson/max_key.py +0 -0
  30. {kover-2.7.0 → kover-2.7.2}/kover/bson/min_key.py +0 -0
  31. {kover-2.7.0 → kover-2.7.2}/kover/bson/objectid.py +0 -0
  32. {kover-2.7.0 → kover-2.7.2}/kover/bson/raw_bson.py +0 -0
  33. {kover-2.7.0 → kover-2.7.2}/kover/bson/regex.py +0 -0
  34. {kover-2.7.0 → kover-2.7.2}/kover/bson/son.py +0 -0
  35. {kover-2.7.0 → kover-2.7.2}/kover/bson/timestamp.py +0 -0
  36. {kover-2.7.0 → kover-2.7.2}/kover/bson/typings.py +0 -0
  37. {kover-2.7.0 → kover-2.7.2}/kover/bson/tz_util.py +0 -0
  38. {kover-2.7.0 → kover-2.7.2}/kover/codes.py +0 -0
  39. {kover-2.7.0 → kover-2.7.2}/kover/collection.py +0 -0
  40. {kover-2.7.0 → kover-2.7.2}/kover/cursor.py +0 -0
  41. {kover-2.7.0 → kover-2.7.2}/kover/enums.py +0 -0
  42. {kover-2.7.0 → kover-2.7.2}/kover/exceptions.py +0 -0
  43. {kover-2.7.0 → kover-2.7.2}/kover/gridfs/__init__.py +0 -0
  44. {kover-2.7.0 → kover-2.7.2}/kover/gridfs/exceptions.py +0 -0
  45. {kover-2.7.0 → kover-2.7.2}/kover/gridfs/gridfs.py +0 -0
  46. {kover-2.7.0 → kover-2.7.2}/kover/gridfs/models.py +0 -0
  47. {kover-2.7.0 → kover-2.7.2}/kover/helpers.py +0 -0
  48. {kover-2.7.0 → kover-2.7.2}/kover/metadata/__init__.py +0 -0
  49. {kover-2.7.0 → kover-2.7.2}/kover/metadata/definitions.py +0 -0
  50. {kover-2.7.0 → kover-2.7.2}/kover/models/__init__.py +0 -0
  51. {kover-2.7.0 → kover-2.7.2}/kover/models/other.py +0 -0
  52. {kover-2.7.0 → kover-2.7.2}/kover/models/replset.py +0 -0
  53. {kover-2.7.0 → kover-2.7.2}/kover/network/__init__.py +0 -0
  54. {kover-2.7.0 → kover-2.7.2}/kover/network/auth.py +0 -0
  55. {kover-2.7.0 → kover-2.7.2}/kover/network/compressors.py +0 -0
  56. {kover-2.7.0 → kover-2.7.2}/kover/network/resolver.py +0 -0
  57. {kover-2.7.0 → kover-2.7.2}/kover/network/wirehelper.py +0 -0
  58. {kover-2.7.0 → kover-2.7.2}/kover/py.typed +0 -0
  59. {kover-2.7.0 → kover-2.7.2}/kover/session.py +0 -0
  60. {kover-2.7.0 → kover-2.7.2}/kover/typings.py +0 -0
  61. {kover-2.7.0 → kover-2.7.2}/kover/uri_parser.py +0 -0
  62. {kover-2.7.0 → kover-2.7.2}/requirements.txt +0 -0
@@ -1,3 +1,4 @@
1
+ uv.lock
1
2
  __pycache__
2
3
  .vscode
3
4
  test.py
@@ -8,6 +9,4 @@ badges.txt
8
9
  dist
9
10
  .ruff_cache
10
11
  .python-version
11
- .token
12
- uv.lock
13
- kover/bulk
12
+ .token
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kover
3
- Version: 2.7.0
3
+ Version: 2.7.2
4
4
  Summary: Fully async mongodb driver for mongod and replica sets.
5
5
  Project-URL: Repository, https://github.com/megawattka/kover
6
6
  Project-URL: Documentation, https://github.com/megawattka/kover
@@ -66,7 +66,7 @@ The main reason why i created this project is that Motor - official async wrappe
66
66
 
67
67
  # Status
68
68
  it still missing features. <br>
69
- e.g: **bulk write API** and **Encryption**
69
+ e.g: **Encryption** and **AWS auth**
70
70
  but its already very cool! <br>
71
71
 
72
72
  # Dependencies
@@ -36,7 +36,7 @@ The main reason why i created this project is that Motor - official async wrappe
36
36
 
37
37
  # Status
38
38
  it still missing features. <br>
39
- e.g: **bulk write API** and **Encryption**
39
+ e.g: **Encryption** and **AWS auth**
40
40
  but its already very cool! <br>
41
41
 
42
42
  # Dependencies
@@ -20,11 +20,12 @@
20
20
  # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  # SOFTWARE.
22
22
 
23
- __version__ = "2.7.0"
23
+ __version__ = "2.7.2"
24
24
  __author__ = "megawattka"
25
25
  __license__ = "MIT"
26
26
  __copyright__ = "Copyright (C) 2024-present megawattka"
27
27
 
28
+ from .bulk_write_builder import BulkWriteBuilder
28
29
  from .client import Kover
29
30
  from .collection import Collection
30
31
  from .cursor import Cursor
@@ -65,6 +66,7 @@ from .typings import xJsonT
65
66
  __all__ = (
66
67
  "AuthCredentials",
67
68
  "BuildInfo",
69
+ "BulkWriteBuilder",
68
70
  "Collation",
69
71
  "CollationStrength",
70
72
  "Collection",
@@ -0,0 +1,104 @@
1
+ """Builder for kover BulkWrite operations."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ from .helpers import filter_non_null
8
+
9
+ if TYPE_CHECKING:
10
+ from .models import Delete, Update
11
+ from .typings import xJsonT
12
+
13
+
14
+ # https://www.mongodb.com/docs/manual/reference/command/bulkWrite
15
+ class BulkWriteBuilder:
16
+ """Builder for bulk write operations."""
17
+
18
+ def __init__(
19
+ self,
20
+ *,
21
+ ordered: bool = True,
22
+ bypass_document_validation: bool = False,
23
+ comment: str | None = None,
24
+ let: xJsonT | None = None,
25
+ errors_only: bool = False,
26
+ cursor_batch_size: int | None = None,
27
+ write_concern: str = "majority",
28
+ ) -> None:
29
+ self.ordered = ordered
30
+ self.bypass_document_validation = bypass_document_validation
31
+ self.comment = comment
32
+ self.let = let
33
+ self.errors_only = errors_only
34
+ self.cursor = {"batchSize": cursor_batch_size or 101}
35
+ self.write_concern = write_concern
36
+ self._operations: list[xJsonT] = []
37
+ self._namespaces: list[str] = []
38
+
39
+ def _prepair_additional_params(self) -> xJsonT:
40
+ return filter_non_null({
41
+ "ordered": self.ordered,
42
+ "bypassDocumentValidation": self.bypass_document_validation,
43
+ "comment": self.comment,
44
+ "let": self.let,
45
+ "errorsOnly": self.errors_only,
46
+ "cursor": self.cursor,
47
+ "writeConcern": {"w": self.write_concern},
48
+ })
49
+
50
+ def _get_ns_idx(self, namespace: str) -> int:
51
+ if namespace not in self._namespaces:
52
+ self._namespaces.append(namespace)
53
+ return self._namespaces.index(namespace)
54
+
55
+ def add_insert(
56
+ self,
57
+ documents: list[xJsonT],
58
+ /,
59
+ *,
60
+ ns: str,
61
+ ) -> None:
62
+ """Adds an Insert operations into the builder."""
63
+ idx = self._get_ns_idx(ns)
64
+ for document in documents:
65
+ self._operations.append({"insert": idx, "document": document})
66
+
67
+ def add_update(
68
+ self,
69
+ *updates: Update,
70
+ ns: str,
71
+ ) -> None:
72
+ """Adds an Update operations into the builder."""
73
+ idx = self._get_ns_idx(ns)
74
+ for update in updates:
75
+ self._operations.append({
76
+ "update": idx,
77
+ **update.as_bulk_write_op(),
78
+ })
79
+
80
+ def add_delete(
81
+ self,
82
+ *deletes: Delete,
83
+ ns: str,
84
+ ) -> None:
85
+ """Adds an Delete operations into the builder."""
86
+ idx = self._get_ns_idx(ns)
87
+ for delete in deletes:
88
+ self._operations.append({
89
+ "delete": idx,
90
+ **delete.as_bulk_write_op(),
91
+ })
92
+
93
+ def build(self) -> xJsonT:
94
+ """Build the command.
95
+
96
+ Returns:
97
+ The command that was built for Kover.bulk_write method.
98
+ """
99
+ return {
100
+ "bulkWrite": 1,
101
+ "ops": self._operations,
102
+ "nsInfo": [{"ns": ns} for ns in self._namespaces],
103
+ **self._prepair_additional_params(),
104
+ }
@@ -239,6 +239,18 @@ class Kover:
239
239
  finally:
240
240
  await self._pool.put(conn)
241
241
 
242
+ async def bulk_write(
243
+ self,
244
+ document: xJsonT,
245
+ transaction: Transaction | None = None,
246
+ ) -> xJsonT:
247
+ """Execute a bulkWrite operation and return info about it.
248
+
249
+ Returns:
250
+ Document, containing info about this operation.
251
+ """
252
+ return await self.request(document, transaction=transaction)
253
+
242
254
  async def refresh_sessions(self, sessions: list[Session]) -> None:
243
255
  """Refresh the provided list of sessions.
244
256
 
@@ -16,7 +16,7 @@ if TYPE_CHECKING:
16
16
  from .typings import xJsonT
17
17
 
18
18
 
19
- @classrepr("name")
19
+ @classrepr("name", "client")
20
20
  class Database:
21
21
  """Represents a database instance, providing methods to manage database.
22
22
 
@@ -2,11 +2,10 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import Literal
6
-
7
5
  from pydantic import BaseModel
8
6
 
9
7
  from .._internals._mixins import ModelMixin as _ModelMixin
8
+ from ..helpers import filter_non_null
10
9
  from ..typings import xJsonT # noqa: TC001
11
10
  from .other import Collation # noqa: TC001
12
11
 
@@ -27,13 +26,29 @@ class Update(_ModelMixin):
27
26
 
28
27
  q: xJsonT
29
28
  u: xJsonT
30
- c: xJsonT | None = None
29
+ c: xJsonT | None = None # constants
31
30
  upsert: bool = False
32
31
  multi: bool = False
33
32
  collation: Collation | None = None
34
33
  array_filters: xJsonT | None = None
35
34
  hint: str | None = None
36
35
 
36
+ def as_bulk_write_op(self) -> xJsonT:
37
+ """Serialize This model for BulkWriteBuilder.
38
+
39
+ Returns:
40
+ Serialized operation.
41
+ """
42
+ return filter_non_null({
43
+ "filter": self.q,
44
+ "updateMods": self.u,
45
+ "arrayFilters": self.array_filters,
46
+ "multi": self.multi,
47
+ "hint": self.hint,
48
+ "constants": self.c,
49
+ "collation": self.collation,
50
+ })
51
+
37
52
 
38
53
  # https://www.mongodb.com/docs/manual/reference/command/delete/#syntax
39
54
  class Delete(_ModelMixin):
@@ -42,7 +57,20 @@ class Delete(_ModelMixin):
42
57
  def __init__(self, q: xJsonT, /, **kwargs: object) -> None:
43
58
  BaseModel.__init__(self, q=q, **kwargs)
44
59
 
45
- q: xJsonT
46
- limit: Literal[0, 1]
60
+ q: xJsonT # query
61
+ limit: int
47
62
  collation: Collation | None = None
48
63
  hint: xJsonT | str | None = None
64
+
65
+ def as_bulk_write_op(self) -> xJsonT:
66
+ """Serialize This model for BulkWriteBuilder.
67
+
68
+ Returns:
69
+ Serialized operation.
70
+ """
71
+ return filter_non_null({
72
+ "filter": self.q,
73
+ "multi": self.limit != 1,
74
+ "hint": self.hint,
75
+ "collation": self.collation,
76
+ })
@@ -76,7 +76,7 @@ class MongoTransport:
76
76
  if not self._writer.is_closing():
77
77
  self._writer.close()
78
78
 
79
- async def send(self, msg: bytes) -> None:
79
+ async def _send(self, msg: bytes) -> None:
80
80
  """Send a message to the MongoDB server.
81
81
 
82
82
  Raises:
@@ -87,7 +87,7 @@ class MongoTransport:
87
87
  self._writer.write(msg)
88
88
  await self._writer.drain()
89
89
 
90
- async def recv(self, size: int) -> bytes:
90
+ async def _recv(self, size: int) -> bytes:
91
91
  """Receive a message from the MongoDB server.
92
92
 
93
93
  Returns:
@@ -119,11 +119,11 @@ class MongoTransport:
119
119
  transaction.apply_to(doc)
120
120
  rid, msg = self._helper.get_message(doc, compressor=self._compressor)
121
121
 
122
- await self.send(msg)
122
+ await self._send(msg)
123
123
  if wait_response:
124
- header = await self.recv(16)
124
+ header = await self._recv(16)
125
125
  length, op_code = self._helper.verify_rid(header, rid)
126
- data = await self.recv(length - 16) # exclude header
126
+ data = await self._recv(length - 16) # exclude header
127
127
  reply = self._helper.get_reply(data, op_code)
128
128
  else: # cases like kover.shutdown()
129
129
  return {}
@@ -202,9 +202,9 @@ class SchemaGenerator:
202
202
 
203
203
  @staticmethod
204
204
  def _generate_metadata(metadata: list[Any]) -> xJsonT:
205
- for _meta in metadata:
206
- if isinstance(_meta, SchemaMetadata):
207
- return _meta.serialize()
205
+ for meta in metadata:
206
+ if isinstance(meta, SchemaMetadata):
207
+ return meta.serialize()
208
208
  return {}
209
209
 
210
210
 
@@ -9,6 +9,7 @@ from typing_extensions import Self
9
9
 
10
10
  from .bson import Int64
11
11
  from .enums import TxnState
12
+ from .helpers import classrepr
12
13
 
13
14
  if TYPE_CHECKING:
14
15
  from types import TracebackType
@@ -17,6 +18,7 @@ if TYPE_CHECKING:
17
18
  from .typings import xJsonT
18
19
 
19
20
 
21
+ @classrepr("_id", "state", "session_document")
20
22
  class Transaction:
21
23
  """Represents a MongoDB transaction.
22
24
 
@@ -36,7 +38,7 @@ class Transaction:
36
38
  ) -> None:
37
39
  self.client = client
38
40
  self.session_document: xJsonT = session_document
39
- self.id: Int64 = Int64(-1)
41
+ self._id: Int64 = Int64(-1)
40
42
  self.state: TxnState = TxnState.NONE
41
43
  self.action_count: int = 0
42
44
  self.exception: BaseException | None = None
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "kover"
3
- version = "2.7.0"
3
+ version = "2.7.2"
4
4
  description = "Fully async mongodb driver for mongod and replica sets."
5
5
  readme = "README.md"
6
6
  authors = [{ name = "megawattka", email = "gunter56741@gmail.com" }]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes