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.
- {kover-2.3.0 → kover-2.6.2}/.gitignore +3 -1
- {kover-2.3.0 → kover-2.6.2}/PKG-INFO +10 -9
- {kover-2.3.0 → kover-2.6.2}/README.md +7 -6
- {kover-2.3.0 → kover-2.6.2}/kover/__init__.py +10 -7
- kover-2.6.2/kover/_internals/__init__.py +7 -0
- {kover-2.3.0 → kover-2.6.2}/kover/_internals/_mixins.py +1 -1
- {kover-2.3.0 → kover-2.6.2}/kover/_internals/_serializers.py +22 -10
- {kover-2.3.0 → kover-2.6.2}/kover/client.py +128 -42
- {kover-2.3.0 → kover-2.6.2}/kover/codes.py +1 -0
- {kover-2.3.0 → kover-2.6.2}/kover/collection.py +23 -32
- {kover-2.3.0 → kover-2.6.2}/kover/cursor.py +1 -1
- {kover-2.3.0 → kover-2.6.2}/kover/database.py +6 -2
- {kover-2.3.0 → kover-2.6.2}/kover/enums.py +8 -0
- {kover-2.3.0 → kover-2.6.2}/kover/exceptions.py +1 -0
- {kover-2.3.0 → kover-2.6.2}/kover/gridfs/__init__.py +2 -2
- {kover-2.3.0 → kover-2.6.2}/kover/gridfs/gridfs.py +3 -2
- kover-2.3.0/kover/utils.py → kover-2.6.2/kover/helpers.py +16 -2
- {kover-2.3.0 → kover-2.6.2}/kover/metadata/__init__.py +2 -2
- {kover-2.3.0 → kover-2.6.2}/kover/metadata/definitions.py +13 -13
- {kover-2.3.0 → kover-2.6.2}/kover/models/__init__.py +3 -3
- {kover-2.3.0 → kover-2.6.2}/kover/models/other.py +14 -2
- kover-2.6.2/kover/network/__init__.py +14 -0
- {kover-2.3.0 → kover-2.6.2}/kover/network/auth.py +95 -56
- {kover-2.3.0 → kover-2.6.2}/kover/network/compressors.py +1 -0
- kover-2.6.2/kover/network/resolver.py +15 -0
- kover-2.6.2/kover/network/transport.py +143 -0
- kover-2.3.0/kover/network/serializer.py → kover-2.6.2/kover/network/wirehelper.py +86 -11
- {kover-2.3.0 → kover-2.6.2}/kover/schema.py +37 -21
- kover-2.6.2/kover/session.py +31 -0
- kover-2.3.0/kover/session.py → kover-2.6.2/kover/transaction.py +8 -38
- {kover-2.3.0 → kover-2.6.2}/kover/typings.py +1 -1
- kover-2.6.2/kover/uri_parser.py +112 -0
- {kover-2.3.0 → kover-2.6.2}/pyproject.toml +6 -14
- kover-2.6.2/requirements.txt +3 -0
- kover-2.3.0/kover/_internals/__init__.py +0 -7
- kover-2.3.0/kover/network/__init__.py +0 -12
- kover-2.3.0/kover/network/msocket.py +0 -179
- kover-2.3.0/kover/network/saslprep.py +0 -116
- kover-2.3.0/requirements.txt +0 -2
- {kover-2.3.0 → kover-2.6.2}/CODE_OF_CONDUCT.md +0 -0
- {kover-2.3.0 → kover-2.6.2}/LICENSE +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/__init__.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/_helpers.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/binary.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/code.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/codec_options.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/datetime_ms.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/dbref.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/decimal128.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/errors.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/int64.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/json_util.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/max_key.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/min_key.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/objectid.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/raw_bson.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/regex.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/son.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/timestamp.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/typings.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/bson/tz_util.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/gridfs/exceptions.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/gridfs/models.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/models/operations.py +0 -0
- /kover-2.3.0/kover/models/replica_set.py → /kover-2.6.2/kover/models/replset.py +0 -0
- {kover-2.3.0 → kover-2.6.2}/kover/py.typed +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: kover
|
|
3
|
-
Version: 2.
|
|
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,
|
|
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
|
|
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
|

|
|
38
38
|

|
|
39
39
|
|
|
40
|
-
**Kover** is a model-orientied
|
|
41
|
-
this library was inspired by <a href=https://github.com/sakal/aiomongo>this project</a> i like it very much. Though its
|
|
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 **
|
|
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.
|
|
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,
|
|
350
|
+
# If you found a bug, open an issue, or even better create a pull request, thx ❤️
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|

|
|
8
8
|

|
|
9
9
|
|
|
10
|
-
**Kover** is a model-orientied
|
|
11
|
-
this library was inspired by <a href=https://github.com/sakal/aiomongo>this project</a> i like it very much. Though its
|
|
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 **
|
|
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.
|
|
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,
|
|
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.
|
|
24
|
-
__author__ = "
|
|
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
|
|
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
|
+
)
|
|
@@ -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 ..
|
|
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:
|
|
74
|
+
# TODO @megawattka: TypedDict support
|
|
68
75
|
def _serialize_dict(
|
|
69
|
-
attr_t: type[object],
|
|
76
|
+
attr_t: type[object],
|
|
70
77
|
/,
|
|
71
78
|
*,
|
|
72
79
|
is_optional: bool = False,
|
|
73
80
|
) -> xJsonT:
|
|
74
|
-
|
|
75
|
-
|
|
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 .
|
|
11
|
-
from .
|
|
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 .
|
|
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
|
-
|
|
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
|
-
|
|
37
|
+
transport: MongoTransport,
|
|
34
38
|
signature: bytes | None,
|
|
39
|
+
*,
|
|
40
|
+
is_primary: bool = False,
|
|
41
|
+
w: str | int = "majority",
|
|
35
42
|
) -> None:
|
|
36
|
-
self.
|
|
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
|
-
|
|
49
|
-
|
|
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
|
|
63
|
+
"""Close the underlying transport connection.
|
|
53
64
|
|
|
54
|
-
This method closes the
|
|
65
|
+
This method closes the transport writer
|
|
55
66
|
and waits until the connection is fully closed.
|
|
56
67
|
"""
|
|
57
|
-
self.
|
|
58
|
-
await self.
|
|
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
|
-
|
|
95
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
133
|
-
return Session(document=req["id"],
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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",
|