1
1
from __future__ import annotations
2
2
3
3
import asyncio
4
+ import contextlib
4
5
import sys
6
+ from typing import Callable
5
7
6
8
import pymongo
7
9
from typing_extensions import Any
8
10
9
11
from pymongo import AsyncMongoClient
10
12
from pymongo .uri_parser import parse_uri
11
13
12
- from test import pytest_conf , db_user , db_pwd
14
+ from test import pytest_conf , db_user , db_pwd , MONGODB_API_VERSION
13
15
from test .asynchronous import async_setup , async_teardown , _connection_string , AsyncClientContext
14
16
15
17
import pytest
@@ -37,6 +39,86 @@ async def async_client_context_fixture():
37
39
yield client
38
40
await client .client .close ()
39
41
42
+ @pytest_asyncio .fixture (loop_scope = "session" , autouse = True )
43
+ async def test_environment (async_client_context_fixture ):
44
+ requirements = {}
45
+ requirements ["SUPPORT_TRANSACTIONS" ] = async_client_context_fixture .supports_transactions ()
46
+ requirements ["IS_DATA_LAKE" ] = async_client_context_fixture .is_data_lake
47
+ requirements ["IS_SYNC" ] = _IS_SYNC
48
+ requirements ["IS_SYNC" ] = _IS_SYNC
49
+ requirements ["REQUIRE_API_VERSION" ] = MONGODB_API_VERSION
50
+ requirements ["SUPPORTS_FAILCOMMAND_FAIL_POINT" ] = async_client_context_fixture .supports_failCommand_fail_point
51
+ requirements ["IS_NOT_MMAP" ] = async_client_context_fixture .is_not_mmap
52
+ requirements ["SERVER_VERSION" ] = async_client_context_fixture .version
53
+ requirements ["AUTH_ENABLED" ] = async_client_context_fixture .auth_enabled
54
+ requirements ["FIPS_ENABLED" ] = async_client_context_fixture .fips_enabled
55
+ requirements ["IS_RS" ] = async_client_context_fixture .is_rs
56
+ requirements ["MONGOSES" ] = len (async_client_context_fixture .mongoses )
57
+ requirements ["SECONDARIES_COUNT" ] = await async_client_context_fixture .secondaries_count
58
+ requirements ["SECONDARY_READ_PREF" ] = await async_client_context_fixture .supports_secondary_read_pref
59
+ requirements ["HAS_IPV6" ] = async_client_context_fixture .has_ipv6
60
+ requirements ["IS_SERVERLESS" ] = async_client_context_fixture .serverless
61
+ requirements ["IS_LOAD_BALANCER" ] = async_client_context_fixture .load_balancer
62
+ requirements ["TEST_COMMANDS_ENABLED" ] = async_client_context_fixture .test_commands_enabled
63
+ requirements ["IS_TLS" ] = async_client_context_fixture .tls
64
+ requirements ["IS_TLS_CERT" ] = async_client_context_fixture .tlsCertificateKeyFile
65
+ requirements ["SERVER_IS_RESOLVEABLE" ] = async_client_context_fixture .server_is_resolvable
66
+ requirements ["SESSIONS_ENABLED" ] = async_client_context_fixture .sessions_enabled
67
+ requirements ["SUPPORTS_RETRYABLE_WRITES" ] = async_client_context_fixture .supports_retryable_writes ()
68
+ yield requirements
69
+
70
+
71
+ @pytest_asyncio .fixture
72
+ async def require_auth (test_environment ):
73
+ if not test_environment ["AUTH_ENABLED" ]:
74
+ pytest .skip ("Authentication is not enabled on the server" )
75
+
76
+ @pytest_asyncio .fixture
77
+ async def require_no_fips (test_environment ):
78
+ if test_environment ["FIPS_ENABLED" ]:
79
+ pytest .skip ("Test cannot run on a FIPS-enabled host" )
80
+
81
+ @pytest_asyncio .fixture
82
+ async def require_no_tls (test_environment ):
83
+ if test_environment ["IS_TLS" ]:
84
+ pytest .skip ("Must be able to connect without TLS" )
85
+
86
+ @pytest_asyncio .fixture
87
+ async def require_ipv6 (test_environment ):
88
+ if not test_environment ["HAS_IPV6" ]:
89
+ pytest .skip ("No IPv6" )
90
+
91
+ @pytest_asyncio .fixture
92
+ async def require_sync (test_environment ):
93
+ if not _IS_SYNC :
94
+ pytest .skip ("This test only works with the synchronous API" )
95
+
96
+ @pytest_asyncio .fixture
97
+ async def require_no_mongos (test_environment ):
98
+ if test_environment ["MONGOSES" ]:
99
+ pytest .skip ("Must be connected to a mongod, not a mongos" )
100
+
101
+ @pytest_asyncio .fixture
102
+ async def require_no_replica_set (test_environment ):
103
+ if test_environment ["IS_RS" ]:
104
+ pytest .skip ("Connected to a replica set, not a standalone mongod" )
105
+
106
+ @pytest_asyncio .fixture
107
+ async def require_replica_set (test_environment ):
108
+ if not test_environment ["IS_RS" ]:
109
+ pytest .skip ("Not connected to a replica set" )
110
+
111
+ @pytest_asyncio .fixture
112
+ async def require_sdam (test_environment ):
113
+ if test_environment ["IS_SERVERLESS" ] or test_environment ["IS_LOAD_BALANCER" ]:
114
+ pytest .skip ("loadBalanced and serverless clients do not run SDAM" )
115
+
116
+ @pytest_asyncio .fixture
117
+ async def require_failCommand_fail_point (test_environment ):
118
+ if not test_environment ["SUPPORTS_FAILCOMMAND_FAIL_POINT" ]:
119
+ pytest .skip ("failCommand fail point must be supported" )
120
+
121
+
40
122
@pytest_asyncio .fixture (loop_scope = "session" , autouse = True )
41
123
async def test_setup_and_teardown ():
42
124
await async_setup ()
@@ -80,12 +162,18 @@ async def async_single_client_noauth(
80
162
) -> AsyncMongoClient [dict ]:
81
163
"""Make a direct connection. Don't authenticate."""
82
164
return await _async_mongo_client (async_client_context , h , p , authenticate = False , directConnection = True , ** kwargs )
83
- #
84
- async def async_single_client (
85
- async_client_context , h : Any = None , p : Any = None , ** kwargs : Any
86
- ) -> AsyncMongoClient [dict ]:
165
+
166
+ @pytest_asyncio .fixture (loop_scope = "session" )
167
+ async def async_single_client (async_client_context_fixture ) -> Callable [..., AsyncMongoClient ]:
87
168
"""Make a direct connection, and authenticate if necessary."""
88
- return await _async_mongo_client (async_client_context , h , p , directConnection = True , ** kwargs )
169
+ clients = []
170
+ async def _make_client (h : Any = None , p : Any = None , ** kwargs : Any ):
171
+ client = await _async_mongo_client (async_client_context_fixture , h , p , directConnection = True , ** kwargs )
172
+ clients .append (client )
173
+ return client
174
+ yield _make_client
175
+ for client in clients :
176
+ await client .close ()
89
177
90
178
# @pytest_asyncio.fixture(loop_scope="function")
91
179
# async def async_rs_client_noauth(
@@ -94,38 +182,64 @@ async def async_single_client(
94
182
# """Connect to the replica set. Don't authenticate."""
95
183
# return await _async_mongo_client(async_client_context, h, p, authenticate=False, **kwargs)
96
184
#
97
- # @pytest_asyncio.fixture(loop_scope="function")
98
- # async def async_rs_client(
99
- # async_client_context, h: Any = None, p: Any = None, **kwargs: Any
100
- # ) -> AsyncMongoClient[dict]:
101
- # """Connect to the replica set and authenticate if necessary."""
102
- # return await _async_mongo_client(async_client_context, h, p, **kwargs)
103
- #
104
- # @pytest_asyncio.fixture(loop_scope="function")
105
- # async def async_rs_or_single_client_noauth(
106
- # async_client_context, h: Any = None, p: Any = None, **kwargs: Any
107
- # ) -> AsyncMongoClient[dict]:
108
- # """Connect to the replica set if there is one, otherwise the standalone.
109
- #
110
- # Like rs_or_single_client, but does not authenticate.
111
- # """
112
- # return await _async_mongo_client(async_client_context, h, p, authenticate=False, **kwargs)
113
185
114
- async def async_rs_or_single_client (
115
- async_client_context , h : Any = None , p : Any = None , ** kwargs : Any
116
- ) -> AsyncMongoClient [Any ]:
186
+ @pytest_asyncio .fixture (loop_scope = "session" )
187
+ async def async_rs_client (async_client_context_fixture ) -> Callable [..., AsyncMongoClient ]:
188
+ """Connect to the replica set and authenticate if necessary."""
189
+ clients = []
190
+ async def _make_client (h : Any = None , p : Any = None , ** kwargs : Any ):
191
+ client = await _async_mongo_client (async_client_context_fixture , h , p , ** kwargs )
192
+ clients .append (client )
193
+ return client
194
+ yield _make_client
195
+ for client in clients :
196
+ await client .close ()
197
+
198
+
199
+ @pytest_asyncio .fixture (loop_scope = "session" )
200
+ async def async_rs_or_single_client_noauth (async_client_context_fixture ) -> Callable [..., AsyncMongoClient ]:
201
+ """Connect to the replica set if there is one, otherwise the standalone.
202
+
203
+ Like rs_or_single_client, but does not authenticate.
204
+ """
205
+ clients = []
206
+ async def _make_client (h : Any = None , p : Any = None , ** kwargs : Any ):
207
+ client = await _async_mongo_client (async_client_context_fixture , h , p , authenticate = False , ** kwargs )
208
+ clients .append (client )
209
+ return client
210
+ yield _make_client
211
+ for client in clients :
212
+ await client .close ()
213
+
214
+ @pytest_asyncio .fixture (loop_scope = "session" )
215
+ async def async_rs_or_single_client (async_client_context_fixture ) -> Callable [..., AsyncMongoClient ]:
117
216
"""Connect to the replica set if there is one, otherwise the standalone.
118
217
119
218
Authenticates if necessary.
120
219
"""
121
- return await _async_mongo_client (async_client_context , h , p , ** kwargs )
122
-
123
- def simple_client (h : Any = None , p : Any = None , ** kwargs : Any ) -> AsyncMongoClient :
124
- if not h and not p :
125
- client = AsyncMongoClient (** kwargs )
126
- else :
127
- client = AsyncMongoClient (h , p , ** kwargs )
128
- return client
220
+ clients = []
221
+ async def _make_client (h : Any = None , p : Any = None , ** kwargs : Any ):
222
+ client = await _async_mongo_client (async_client_context_fixture , h , p , ** kwargs )
223
+ clients .append (client )
224
+ return client
225
+ yield _make_client
226
+ for client in clients :
227
+ await client .close ()
228
+
229
+
230
+ @pytest_asyncio .fixture (loop_scope = "session" )
231
+ async def simple_client () -> Callable [..., AsyncMongoClient ]:
232
+ clients = []
233
+ async def _make_client (h : Any = None , p : Any = None , ** kwargs : Any ):
234
+ if not h and not p :
235
+ client = AsyncMongoClient (** kwargs )
236
+ else :
237
+ client = AsyncMongoClient (h , p , ** kwargs )
238
+ clients .append (client )
239
+ return client
240
+ yield _make_client
241
+ for client in clients :
242
+ await client .close ()
129
243
130
244
@pytest .fixture (scope = "function" )
131
245
def patch_resolver ():
0 commit comments