kover 2.3.0__tar.gz → 2.6.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 (66) hide show
  1. {kover-2.3.0 → kover-2.6.2}/.gitignore +3 -1
  2. {kover-2.3.0 → kover-2.6.2}/PKG-INFO +10 -9
  3. {kover-2.3.0 → kover-2.6.2}/README.md +7 -6
  4. {kover-2.3.0 → kover-2.6.2}/kover/__init__.py +10 -7
  5. kover-2.6.2/kover/_internals/__init__.py +7 -0
  6. {kover-2.3.0 → kover-2.6.2}/kover/_internals/_mixins.py +1 -1
  7. {kover-2.3.0 → kover-2.6.2}/kover/_internals/_serializers.py +22 -10
  8. {kover-2.3.0 → kover-2.6.2}/kover/client.py +128 -42
  9. {kover-2.3.0 → kover-2.6.2}/kover/codes.py +1 -0
  10. {kover-2.3.0 → kover-2.6.2}/kover/collection.py +23 -32
  11. {kover-2.3.0 → kover-2.6.2}/kover/cursor.py +1 -1
  12. {kover-2.3.0 → kover-2.6.2}/kover/database.py +6 -2
  13. {kover-2.3.0 → kover-2.6.2}/kover/enums.py +8 -0
  14. {kover-2.3.0 → kover-2.6.2}/kover/exceptions.py +1 -0
  15. {kover-2.3.0 → kover-2.6.2}/kover/gridfs/__init__.py +2 -2
  16. {kover-2.3.0 → kover-2.6.2}/kover/gridfs/gridfs.py +3 -2
  17. kover-2.3.0/kover/utils.py → kover-2.6.2/kover/helpers.py +16 -2
  18. {kover-2.3.0 → kover-2.6.2}/kover/metadata/__init__.py +2 -2
  19. {kover-2.3.0 → kover-2.6.2}/kover/metadata/definitions.py +13 -13
  20. {kover-2.3.0 → kover-2.6.2}/kover/models/__init__.py +3 -3
  21. {kover-2.3.0 → kover-2.6.2}/kover/models/other.py +14 -2
  22. kover-2.6.2/kover/network/__init__.py +14 -0
  23. {kover-2.3.0 → kover-2.6.2}/kover/network/auth.py +95 -56
  24. {kover-2.3.0 → kover-2.6.2}/kover/network/compressors.py +1 -0
  25. kover-2.6.2/kover/network/resolver.py +15 -0
  26. kover-2.6.2/kover/network/transport.py +143 -0
  27. kover-2.3.0/kover/network/serializer.py → kover-2.6.2/kover/network/wirehelper.py +86 -11
  28. {kover-2.3.0 → kover-2.6.2}/kover/schema.py +37 -21
  29. kover-2.6.2/kover/session.py +31 -0
  30. kover-2.3.0/kover/session.py → kover-2.6.2/kover/transaction.py +8 -38
  31. {kover-2.3.0 → kover-2.6.2}/kover/typings.py +1 -1
  32. kover-2.6.2/kover/uri_parser.py +112 -0
  33. {kover-2.3.0 → kover-2.6.2}/pyproject.toml +6 -14
  34. kover-2.6.2/requirements.txt +3 -0
  35. kover-2.3.0/kover/_internals/__init__.py +0 -7
  36. kover-2.3.0/kover/network/__init__.py +0 -12
  37. kover-2.3.0/kover/network/msocket.py +0 -179
  38. kover-2.3.0/kover/network/saslprep.py +0 -116
  39. kover-2.3.0/requirements.txt +0 -2
  40. {kover-2.3.0 → kover-2.6.2}/CODE_OF_CONDUCT.md +0 -0
  41. {kover-2.3.0 → kover-2.6.2}/LICENSE +0 -0
  42. {kover-2.3.0 → kover-2.6.2}/kover/bson/__init__.py +0 -0
  43. {kover-2.3.0 → kover-2.6.2}/kover/bson/_helpers.py +0 -0
  44. {kover-2.3.0 → kover-2.6.2}/kover/bson/binary.py +0 -0
  45. {kover-2.3.0 → kover-2.6.2}/kover/bson/code.py +0 -0
  46. {kover-2.3.0 → kover-2.6.2}/kover/bson/codec_options.py +0 -0
  47. {kover-2.3.0 → kover-2.6.2}/kover/bson/datetime_ms.py +0 -0
  48. {kover-2.3.0 → kover-2.6.2}/kover/bson/dbref.py +0 -0
  49. {kover-2.3.0 → kover-2.6.2}/kover/bson/decimal128.py +0 -0
  50. {kover-2.3.0 → kover-2.6.2}/kover/bson/errors.py +0 -0
  51. {kover-2.3.0 → kover-2.6.2}/kover/bson/int64.py +0 -0
  52. {kover-2.3.0 → kover-2.6.2}/kover/bson/json_util.py +0 -0
  53. {kover-2.3.0 → kover-2.6.2}/kover/bson/max_key.py +0 -0
  54. {kover-2.3.0 → kover-2.6.2}/kover/bson/min_key.py +0 -0
  55. {kover-2.3.0 → kover-2.6.2}/kover/bson/objectid.py +0 -0
  56. {kover-2.3.0 → kover-2.6.2}/kover/bson/raw_bson.py +0 -0
  57. {kover-2.3.0 → kover-2.6.2}/kover/bson/regex.py +0 -0
  58. {kover-2.3.0 → kover-2.6.2}/kover/bson/son.py +0 -0
  59. {kover-2.3.0 → kover-2.6.2}/kover/bson/timestamp.py +0 -0
  60. {kover-2.3.0 → kover-2.6.2}/kover/bson/typings.py +0 -0
  61. {kover-2.3.0 → kover-2.6.2}/kover/bson/tz_util.py +0 -0
  62. {kover-2.3.0 → kover-2.6.2}/kover/gridfs/exceptions.py +0 -0
  63. {kover-2.3.0 → kover-2.6.2}/kover/gridfs/models.py +0 -0
  64. {kover-2.3.0 → kover-2.6.2}/kover/models/operations.py +0 -0
  65. /kover-2.3.0/kover/models/replica_set.py → /kover-2.6.2/kover/models/replset.py +0 -0
  66. {kover-2.3.0 → kover-2.6.2}/kover/py.typed +0 -0
@@ -8,4 +8,6 @@ badges.txt
8
8
  dist
9
9
  .ruff_cache
10
10
  .python-version
11
- .token
11
+ .token
12
+ uv.lock
13
+ kover/bulk
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kover
3
- Version: 2.3.0
3
+ Version: 2.6.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
7
7
  Author-email: megawattka <gunter56741@gmail.com>
8
8
  License-Expression: MIT
9
9
  License-File: LICENSE
10
- Keywords: Kover API mongo,Mongo Kover,async driver,kover,kover mongodb,megawattka,mongo async,mongo kover,mongod driver,mongodb
10
+ Keywords: Kover API mongo,Mongo Kover,async driver,kover,kover mongodb,mongo async,mongo kover,mongod driver,mongodb
11
11
  Classifier: Development Status :: 4 - Beta
12
12
  Classifier: Intended Audience :: Developers
13
13
  Classifier: License :: OSI Approved :: MIT License
@@ -19,7 +19,7 @@ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
19
  Classifier: Topic :: Software Development :: Quality Assurance
20
20
  Classifier: Typing :: Typed
21
21
  Requires-Python: >=3.10
22
- Requires-Dist: dnspython<3.0.0,>=1.16.0
22
+ Requires-Dist: dnspython>=2.7.0
23
23
  Requires-Dist: pydantic>=2.10.6
24
24
  Requires-Dist: typing-extensions>=4.12.2
25
25
  Provides-Extra: snappy
@@ -37,8 +37,8 @@ Description-Content-Type: text/markdown
37
37
  ![Last Commit](https://img.shields.io/github/last-commit/megawattka/kover)
38
38
  ![MongoDB](https://img.shields.io/badge/MongoDB-6.0+-green)
39
39
 
40
- **Kover** is a model-orientied strict typed mongodb driver supporting local mongod and replica sets. Battle tests are still required*<br>
41
- this library was inspired by <a href=https://github.com/sakal/aiomongo>this project</a> i like it very much. Though its 8 years old.
40
+ **Kover** is a model-orientied strictly typed mongodb driver supporting local mongod, replica sets and remote atlases.<br>
41
+ this library was inspired by <a href=https://github.com/sakal/aiomongo>this project</a> i like it very much. Though its 9 years old.
42
42
  Kover is linted by Ruff and supports pyright strict type checking mode.
43
43
 
44
44
  ```py
@@ -66,19 +66,20 @@ 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 **Compression**<br>
69
+ e.g: **bulk write API** and **Encryption**
70
70
  but its already very cool! <br>
71
71
 
72
72
  # Dependencies
73
73
  - All platforms.
74
- - python 3.10
74
+ - python 3.10+
75
75
  - MongoDB 6.0+ (not sure about older versions)
76
76
  - pydantic 2.10.6 or later
77
+ - dnspython 2.7.0 or later
77
78
 
78
79
  # Features
79
80
  Almost all features from pymongo. All auth types are supported. Integration with Pydantic supported.
80
81
  this lib was built for new mongod versions. All features that were marked as DEPRECATED in docs
81
- were NOT added. See docs for references. The kover.bson package was entirely copied from pymongo source code. Also pymongo.saslprep was copied for internal purposes, i do not own these files.
82
+ were NOT added. See docs for references. The kover.bson package was entirely copied from pymongo source code. I do not own these files.
82
83
 
83
84
  ### Cursors
84
85
  if you just need list:
@@ -346,4 +347,4 @@ if __name__ == "__main__":
346
347
 
347
348
  ```
348
349
 
349
- # If you found a bug, go ahead and open an issue, or even better a pull request, thx ❤️
350
+ # If you found a bug, open an issue, or even better create a pull request, thx ❤️
@@ -7,8 +7,8 @@
7
7
  ![Last Commit](https://img.shields.io/github/last-commit/megawattka/kover)
8
8
  ![MongoDB](https://img.shields.io/badge/MongoDB-6.0+-green)
9
9
 
10
- **Kover** is a model-orientied strict typed mongodb driver supporting local mongod and replica sets. Battle tests are still required*<br>
11
- this library was inspired by <a href=https://github.com/sakal/aiomongo>this project</a> i like it very much. Though its 8 years old.
10
+ **Kover** is a model-orientied strictly typed mongodb driver supporting local mongod, replica sets and remote atlases.<br>
11
+ this library was inspired by <a href=https://github.com/sakal/aiomongo>this project</a> i like it very much. Though its 9 years old.
12
12
  Kover is linted by Ruff and supports pyright strict type checking mode.
13
13
 
14
14
  ```py
@@ -36,19 +36,20 @@ 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 **Compression**<br>
39
+ e.g: **bulk write API** and **Encryption**
40
40
  but its already very cool! <br>
41
41
 
42
42
  # Dependencies
43
43
  - All platforms.
44
- - python 3.10
44
+ - python 3.10+
45
45
  - MongoDB 6.0+ (not sure about older versions)
46
46
  - pydantic 2.10.6 or later
47
+ - dnspython 2.7.0 or later
47
48
 
48
49
  # Features
49
50
  Almost all features from pymongo. All auth types are supported. Integration with Pydantic supported.
50
51
  this lib was built for new mongod versions. All features that were marked as DEPRECATED in docs
51
- were NOT added. See docs for references. The kover.bson package was entirely copied from pymongo source code. Also pymongo.saslprep was copied for internal purposes, i do not own these files.
52
+ were NOT added. See docs for references. The kover.bson package was entirely copied from pymongo source code. I do not own these files.
52
53
 
53
54
  ### Cursors
54
55
  if you just need list:
@@ -316,4 +317,4 @@ if __name__ == "__main__":
316
317
 
317
318
  ```
318
319
 
319
- # If you found a bug, go ahead and open an issue, or even better a pull request, thx ❤️
320
+ # If you found a bug, open an issue, or even better create a pull request, thx ❤️
@@ -20,8 +20,8 @@
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.3.0"
24
- __author__ = "oMegaPB"
23
+ __version__ = "2.6.2"
24
+ __author__ = "megawattka"
25
25
  __license__ = "MIT"
26
26
  __copyright__ = "Copyright (C) 2024-present megawattka"
27
27
 
@@ -41,6 +41,7 @@ from .exceptions import (
41
41
  OperationFailure,
42
42
  SchemaGenerationException,
43
43
  )
44
+ from .helpers import chain, filter_non_null, maybe_to_dict
44
45
  from .models import (
45
46
  BuildInfo,
46
47
  Collation,
@@ -55,13 +56,13 @@ from .models import (
55
56
  User,
56
57
  WriteConcern,
57
58
  )
58
- from .network import AuthCredentials
59
+ from .network import AuthCredentials, MongoTransport, SrvResolver
59
60
  from .schema import Document, SchemaGenerator
60
- from .session import Session, Transaction
61
+ from .session import Session
62
+ from .transaction import Transaction
61
63
  from .typings import xJsonT
62
- from .utils import chain, filter_non_null, maybe_to_dict
63
64
 
64
- __all__ = [
65
+ __all__ = (
65
66
  "AuthCredentials",
66
67
  "BuildInfo",
67
68
  "Collation",
@@ -78,6 +79,7 @@ __all__ = [
78
79
  "IndexDirection",
79
80
  "IndexType",
80
81
  "Kover",
82
+ "MongoTransport",
81
83
  "OperationFailure",
82
84
  "ReadConcern",
83
85
  "ReplicaSetConfig",
@@ -86,6 +88,7 @@ __all__ = [
86
88
  "SchemaGenerationException",
87
89
  "SchemaGenerator",
88
90
  "Session",
91
+ "SrvResolver",
89
92
  "Transaction",
90
93
  "Update",
91
94
  "User",
@@ -95,4 +98,4 @@ __all__ = [
95
98
  "filter_non_null",
96
99
  "maybe_to_dict",
97
100
  "xJsonT",
98
- ]
101
+ )
@@ -0,0 +1,7 @@
1
+ from ._mixins import EmptyReprMixin
2
+ from ._serializers import value_to_json_schema
3
+
4
+ __all__ = (
5
+ "EmptyReprMixin",
6
+ "value_to_json_schema",
7
+ )
@@ -9,7 +9,7 @@ if TYPE_CHECKING:
9
9
  from ..typings import xJsonT
10
10
 
11
11
 
12
- class ReprMixin:
12
+ class EmptyReprMixin:
13
13
  def __repr__(self) -> str:
14
14
  return f"{self.__class__.__name__}()"
15
15
 
@@ -8,11 +8,14 @@ from typing import (
8
8
  Literal,
9
9
  get_origin,
10
10
  )
11
+ from typing import is_typeddict as t_is_typeddict
11
12
  from uuid import UUID
12
13
 
14
+ from typing_extensions import is_typeddict as te_is_typeddict
15
+
13
16
  from ..bson import Binary, Int64, ObjectId, Timestamp
14
- from ..exceptions import UnsupportedAnnotation
15
- from ..utils import chain
17
+ from ..exceptions import SchemaGenerationException, UnsupportedAnnotation
18
+ from ..helpers import chain
16
19
 
17
20
  if TYPE_CHECKING:
18
21
  from types import UnionType
@@ -60,20 +63,27 @@ def _serialize_literal(
60
63
  }
61
64
 
62
65
 
66
+ def _is_typeddict_ex(attr_t: type[object]) -> bool:
67
+ return t_is_typeddict(attr_t) or te_is_typeddict(attr_t)
68
+
69
+
63
70
  # passing type data to dict unsupported and ignored
64
71
  # use Document for that
65
72
  # in that case it just creates AnyDict
66
73
  # accepting any data passed to it. e.g custom metadata
67
- # TODO @megawattka: probably add something here?
74
+ # TODO @megawattka: TypedDict support
68
75
  def _serialize_dict(
69
- attr_t: type[object], # noqa: ARG001
76
+ attr_t: type[object],
70
77
  /,
71
78
  *,
72
79
  is_optional: bool = False,
73
80
  ) -> xJsonT:
74
- return {
75
- "bsonType": ["object"] + (["null"] if is_optional else []),
76
- }
81
+ if not _is_typeddict_ex(attr_t):
82
+ return {
83
+ "bsonType": ["object"] + (["null"] if is_optional else []),
84
+ }
85
+ comment = "TypedDict currently not supported. Use Document."
86
+ raise SchemaGenerationException(comment)
77
87
 
78
88
 
79
89
  def _serialize_enum(
@@ -105,12 +115,15 @@ def _serialize_simple_type(
105
115
 
106
116
 
107
117
  def value_to_json_schema(
108
- attr_t: object,
118
+ attr_t: type[object],
109
119
  /,
110
120
  *,
111
121
  is_optional: bool = False,
112
122
  ) -> xJsonT | None:
113
123
  origin = get_origin(attr_t)
124
+ if origin is None and _is_typeddict_ex(attr_t):
125
+ origin = dict
126
+
114
127
  func = None
115
128
  origin_map: dict[Any, Any] = {
116
129
  Literal: _serialize_literal,
@@ -119,12 +132,11 @@ def value_to_json_schema(
119
132
  if origin in origin_map:
120
133
  func = origin_map[origin] # type: ignore
121
134
 
122
- elif isinstance(attr_t, type) and issubclass(attr_t, Enum):
135
+ elif isinstance(attr_t, type) and issubclass(attr_t, Enum): # type: ignore
123
136
  func = _serialize_enum
124
137
 
125
138
  elif attr_t in _TYPE_MAP:
126
139
  func = _serialize_simple_type
127
-
128
140
  if func is not None:
129
141
  return func(attr_t, is_optional=is_optional) # type: ignore
130
142
 
@@ -1,16 +1,16 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import json
4
- import random
5
4
  from typing import TYPE_CHECKING, Literal
6
5
 
7
6
  from typing_extensions import Self
8
7
 
9
8
  from .database import Database
10
- from .models import BuildInfo
11
- from .network import Auth, MongoSocket
9
+ from .helpers import classrepr, filter_non_null, maybe_to_dict
10
+ from .models import BuildInfo, WriteConcern
11
+ from .network import MongoTransport, SrvResolver
12
12
  from .session import Session
13
- from .utils import filter_non_null, maybe_to_dict
13
+ from .uri_parser import parse_uri
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  import asyncio
@@ -20,21 +20,30 @@ if TYPE_CHECKING:
20
20
  from .typings import COMPRESSION_T, xJsonT
21
21
 
22
22
 
23
+ @classrepr("signature", "transport", "is_primary")
23
24
  class Kover:
24
25
  """Kover client for interacting with a MongoDB server.
25
26
 
26
27
  Attributes:
27
- socket : The underlying socket connection to the MongoDB server.
28
+ transport : The underlying transport to the MongoDB server.
28
29
  signature : The authentication signature, if authenticated.
30
+ default_database : The name of the default database.
31
+ is_primary : The flag that tells us whether that
32
+ this is primary or secondary instance
29
33
  """
30
34
 
31
35
  def __init__(
32
36
  self,
33
- socket: MongoSocket,
37
+ transport: MongoTransport,
34
38
  signature: bytes | None,
39
+ *,
40
+ is_primary: bool = False,
41
+ w: str | int = "majority",
35
42
  ) -> None:
36
- self.socket: MongoSocket = socket
43
+ self.transport = transport
37
44
  self.signature = signature
45
+ self._is_primary = is_primary
46
+ self._write_concern = WriteConcern(w=w)
38
47
 
39
48
  async def __aenter__(self) -> Self:
40
49
  return self
@@ -45,17 +54,19 @@ class Kover:
45
54
  await self.close()
46
55
  return True
47
56
 
48
- def __repr__(self) -> str:
49
- return f"<Kover signature={self.signature} socket={self.socket}>"
57
+ @property
58
+ def is_primary(self) -> bool:
59
+ """Whether this instance is a primary or not."""
60
+ return self._is_primary
50
61
 
51
62
  async def close(self) -> None:
52
- """Close the underlying socket connection.
63
+ """Close the underlying transport connection.
53
64
 
54
- This method closes the socket writer
65
+ This method closes the transport writer
55
66
  and waits until the connection is fully closed.
56
67
  """
57
- self.socket.writer.close()
58
- await self.socket.writer.wait_closed()
68
+ self.transport.writer.close()
69
+ await self.transport.writer.wait_closed()
59
70
 
60
71
  def get_database(self, name: str) -> Database:
61
72
  """Get a Database instance for the specified database name.
@@ -71,14 +82,74 @@ class Kover:
71
82
  def __getattr__(self, name: str) -> Database:
72
83
  return self.get_database(name=name)
73
84
 
85
+ def set_write_concern(
86
+ self,
87
+ /,
88
+ *,
89
+ w: str | int,
90
+ j: bool | None = None,
91
+ wtimeout: int = 0,
92
+ ) -> Self:
93
+ """This sets a WriteConcern for all requests."""
94
+ self._write_concern = WriteConcern(w=w, j=j, wtimeout=wtimeout)
95
+ return self
96
+
97
+ @classmethod
98
+ async def from_uri(
99
+ cls,
100
+ uri: str,
101
+ loop: asyncio.AbstractEventLoop | None = None,
102
+ ) -> Kover:
103
+ """Create an instance of Kover client by passing a uri."""
104
+ parsed = parse_uri(uri)
105
+
106
+ resolver = SrvResolver()
107
+ nodes = await resolver.get_nodes(parsed.hostname)
108
+ assert nodes, "Node resolution failed."
109
+
110
+ transport = await MongoTransport.make(
111
+ nodes[0], port=parsed.port, tls=parsed.tls, loop=loop)
112
+
113
+ hello = await transport.hello(
114
+ parsed.compressors, parsed.credentials, parsed.application)
115
+
116
+ if not hello.is_primary:
117
+ assert hello.primary_node, "Primary node resolution failed."
118
+
119
+ host, _ = hello.primary_node.split(":")
120
+ return await cls.make_client(
121
+ host=host,
122
+ port=parsed.port,
123
+ credentials=parsed.credentials,
124
+ loop=loop,
125
+ compression=parsed.compressors,
126
+ tls=parsed.tls,
127
+ application=parsed.application,
128
+ write_concern=parsed.write_concern,
129
+ )
130
+
131
+ mechanism = hello.get_auth_mechanism()
132
+ signature = await transport.authorize(mechanism, parsed.credentials)
133
+
134
+ return cls(
135
+ transport=transport,
136
+ signature=signature,
137
+ is_primary=hello.is_primary,
138
+ w=parsed.write_concern,
139
+ )
140
+
74
141
  @classmethod
75
142
  async def make_client(
76
143
  cls,
77
144
  host: str = "127.0.0.1",
78
145
  port: int = 27017,
146
+ *,
79
147
  credentials: AuthCredentials | None = None,
80
148
  loop: asyncio.AbstractEventLoop | None = None,
81
149
  compression: COMPRESSION_T | None = None,
150
+ tls: bool = False,
151
+ application: xJsonT | None = None,
152
+ write_concern: str | int = "majority",
82
153
  ) -> Kover:
83
154
  """Create and return a new Kover client instance.
84
155
 
@@ -87,23 +158,34 @@ class Kover:
87
158
  port : The port number of the MongoDB server, by default 27017.
88
159
  credentials : Authentication credentials, if required.
89
160
  loop : The event loop to use for asynchronous operations.
161
+ compression : List of compression options.
162
+ default_database : the name of a database that will be returned
163
+ by Kover.get_default_database().
164
+ tls : the boolean value that indicated whether to use tls or no.
165
+ application : document that will be included in hello payload
166
+ under the "application" field.
167
+ write_concern : the value of default write concern used.
90
168
 
91
169
  Returns:
92
170
  An instance of the Kover client.
93
171
  """
94
- socket = await MongoSocket.make(host=host, port=port, loop=loop)
95
- hello = await socket.hello(
172
+ transport = await MongoTransport.make(
173
+ host=host, port=port, loop=loop, tls=tls)
174
+
175
+ hello = await transport.hello(
96
176
  credentials=credentials,
97
177
  compression=compression,
178
+ application=application,
179
+ )
180
+ mechanism = hello.get_auth_mechanism()
181
+ signature = await transport.authorize(mechanism, credentials)
182
+
183
+ return cls(
184
+ transport,
185
+ signature,
186
+ is_primary=hello.is_primary,
187
+ w=write_concern,
98
188
  )
99
- if hello.requires_auth and credentials:
100
- mechanism = random.choice(hello.sasl_supported_mechs or []) # noqa: S311
101
- signature = await Auth(socket).create(mechanism, credentials)
102
- else:
103
- signature = None
104
- if hello.compression:
105
- socket.set_compressor(hello.compression[0])
106
- return cls(socket, signature)
107
189
 
108
190
  async def refresh_sessions(self, sessions: list[Session]) -> None:
109
191
  """Refresh the provided list of sessions.
@@ -112,7 +194,7 @@ class Kover:
112
194
  sessions : A list of Session objects to be refreshed.
113
195
  """
114
196
  documents: list[xJsonT] = [x.document for x in sessions]
115
- await self.socket.request({"refreshSessions": documents})
197
+ await self.transport.request({"refreshSessions": documents})
116
198
 
117
199
  async def end_sessions(self, sessions: list[Session]) -> None:
118
200
  """End the provided list of sessions.
@@ -121,7 +203,7 @@ class Kover:
121
203
  sessions : A list of Session objects to be ended.
122
204
  """
123
205
  documents: list[xJsonT] = [x.document for x in sessions]
124
- await self.socket.request({"endSessions": documents})
206
+ await self.transport.request({"endSessions": documents})
125
207
 
126
208
  async def start_session(self) -> Session:
127
209
  """Start a new session.
@@ -129,8 +211,8 @@ class Kover:
129
211
  Returns:
130
212
  An instance of the Session class representing the started session.
131
213
  """
132
- req = await self.socket.request({"startSession": 1.0})
133
- return Session(document=req["id"], socket=self.socket)
214
+ req = await self.transport.request({"startSession": 1.0})
215
+ return Session(document=req["id"], transport=self.transport)
134
216
 
135
217
  async def build_info(self) -> BuildInfo:
136
218
  """Retrieve build information from the MongoDB server.
@@ -138,7 +220,7 @@ class Kover:
138
220
  Returns:
139
221
  An instance of BuildInfo containing server build details.
140
222
  """
141
- request = await self.socket.request({"buildInfo": 1.0})
223
+ request = await self.transport.request({"buildInfo": 1.0})
142
224
  return BuildInfo.model_validate(request)
143
225
 
144
226
  async def logout(self) -> None:
@@ -147,7 +229,7 @@ class Kover:
147
229
  This method sends a logout request to the server
148
230
  to terminate the current authenticated session.
149
231
  """
150
- await self.socket.request({"logout": 1.0})
232
+ await self.transport.request({"logout": 1.0})
151
233
 
152
234
  async def list_database_names(self) -> list[str]:
153
235
  """Retrieve the names of all databases on the MongoDB server.
@@ -159,7 +241,7 @@ class Kover:
159
241
  "listDatabases": 1.0,
160
242
  "nameOnly": True # noqa: COM812
161
243
  }
162
- request = await self.socket.request(command)
244
+ request = await self.transport.request(command)
163
245
  return [x["name"] for x in request["databases"]]
164
246
 
165
247
  async def drop_database(self, name: str) -> None:
@@ -168,7 +250,7 @@ class Kover:
168
250
  Parameters:
169
251
  name : The name of the database to drop.
170
252
  """
171
- await self.socket.request({"dropDatabase": 1.0}, db_name=name)
253
+ await self.transport.request({"dropDatabase": 1.0}, db_name=name)
172
254
 
173
255
  # https://www.mongodb.com/docs/manual/reference/command/replSetInitiate/
174
256
  async def replica_set_initiate(
@@ -182,12 +264,13 @@ class Kover:
182
264
  default configuration is used.
183
265
  """
184
266
  document = maybe_to_dict(config) or {}
185
- await self.socket.request({"replSetInitiate": document})
267
+ await self.transport.request({"replSetInitiate": document})
186
268
 
187
269
  # https://www.mongodb.com/docs/manual/reference/command/replSetReconfig/
188
270
  async def replica_set_reconfig(
189
271
  self,
190
272
  config: ReplicaSetConfig,
273
+ *,
191
274
  force: bool = False,
192
275
  max_time_ms: int | None = None,
193
276
  ) -> None:
@@ -201,7 +284,7 @@ class Kover:
201
284
  "force": force,
202
285
  "maxTimeMS": max_time_ms,
203
286
  })
204
- await self.socket.request(document)
287
+ await self.transport.request(document)
205
288
 
206
289
  # https://www.mongodb.com/docs/manual/reference/command/replSetGetStatus/
207
290
  async def get_replica_set_status(self) -> xJsonT:
@@ -210,11 +293,12 @@ class Kover:
210
293
  Returns:
211
294
  A JSON document containing the replica set status information.
212
295
  """
213
- return await self.socket.request({"replSetGetStatus": 1.0})
296
+ return await self.transport.request({"replSetGetStatus": 1.0})
214
297
 
215
298
  # https://www.mongodb.com/docs/manual/reference/command/shutdown/
216
299
  async def shutdown(
217
300
  self,
301
+ *,
218
302
  force: bool = False,
219
303
  timeout: int | None = None,
220
304
  comment: str | None = None,
@@ -232,7 +316,7 @@ class Kover:
232
316
  "timeoutSecs": timeout,
233
317
  "comment": comment,
234
318
  })
235
- await self.socket.request(command, wait_response=False)
319
+ await self.transport.request(command, wait_response=False)
236
320
 
237
321
  # https://www.mongodb.com/docs/manual/reference/command/getCmdLineOpts/
238
322
  async def get_commandline(self) -> list[str]:
@@ -241,7 +325,7 @@ class Kover:
241
325
  Returns:
242
326
  A list of command line arguments.
243
327
  """
244
- r = await self.socket.request({"getCmdLineOpts": 1.0})
328
+ r = await self.transport.request({"getCmdLineOpts": 1.0})
245
329
  return r["argv"]
246
330
 
247
331
  # https://www.mongodb.com/docs/manual/reference/command/getLog/#getlog
@@ -258,7 +342,7 @@ class Kover:
258
342
  Returns:
259
343
  A list of log entries as JSON objects.
260
344
  """
261
- r = await self.socket.request({"getLog": parameter})
345
+ r = await self.transport.request({"getLog": parameter})
262
346
  return [
263
347
  json.loads(info) for info in r["log"]
264
348
  ]
@@ -267,6 +351,7 @@ class Kover:
267
351
  async def rename_collection(
268
352
  self,
269
353
  target: str,
354
+ *,
270
355
  new_name: str,
271
356
  drop_target: bool = False,
272
357
  comment: str | None = None,
@@ -286,17 +371,17 @@ class Kover:
286
371
  "dropTarget": drop_target,
287
372
  "comment": comment,
288
373
  })
289
- await self.socket.request(command)
374
+ await self.transport.request(command)
290
375
 
291
376
  # https://www.mongodb.com/docs/manual/reference/command/setUserWriteBlockMode/
292
- async def set_user_write_block_mode(self, param: bool) -> None:
377
+ async def set_user_write_block_mode(self, *, param: bool) -> None:
293
378
  """Set the user write block mode on the MongoDB server.
294
379
 
295
380
  Parameters:
296
381
  param : Blocks writes on a cluster when set to true.
297
382
  To enable writes on a cluster, set global: false.
298
383
  """
299
- await self.socket.request({
384
+ await self.transport.request({
300
385
  "setUserWriteBlockMode": 1.0,
301
386
  "global": param,
302
387
  })
@@ -304,6 +389,7 @@ class Kover:
304
389
  # https://www.mongodb.com/docs/manual/reference/command/fsync/
305
390
  async def fsync(
306
391
  self,
392
+ *,
307
393
  timeout: int = 90000,
308
394
  lock: bool = True,
309
395
  comment: str | None = None,
@@ -323,7 +409,7 @@ class Kover:
323
409
  "lock": lock,
324
410
  "comment": comment,
325
411
  })
326
- await self.socket.request(command)
412
+ await self.transport.request(command)
327
413
 
328
414
  # https://www.mongodb.com/docs/manual/reference/command/fsyncUnlock/
329
415
  async def fsync_unlock(self, comment: str | None = None) -> None:
@@ -336,4 +422,4 @@ class Kover:
336
422
  "fsyncUnlock": 1.0,
337
423
  "comment": comment,
338
424
  })
339
- await self.socket.request(command)
425
+ await self.transport.request(command)
@@ -424,6 +424,7 @@ _codes_to_exc_name: dict[str, str] = {
424
424
  "457": "ReplayClientInternalError",
425
425
  "458": "ReplayClientSessionSchedulerError",
426
426
  "459": "ReplayClientSessionSimulationError",
427
+ "8000": "AtlasError",
427
428
  "9001": "SocketException",
428
429
  "10003": "CannotGrowDocumentInCappedNamespace",
429
430
  "10058": "LegacyNotPrimary",