Skip to content

Commit c6d2ceb

Browse files
committed
address comments
1 parent d450457 commit c6d2ceb

File tree

7 files changed

+122
-220
lines changed

7 files changed

+122
-220
lines changed

pymongo/asynchronous/mongo_client.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,10 @@
5959
cast,
6060
)
6161

62-
import pymongo.asynchronous.uri_parser
62+
import pymongo.uri_parser_shared
6363
from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions, TypeRegistry
6464
from bson.timestamp import Timestamp
65-
from pymongo import _csot, common, helpers_shared, periodic_executor, uri_parser_shared
65+
from pymongo import _csot, common, helpers_shared, periodic_executor
6666
from pymongo.asynchronous import client_session, database, uri_parser
6767
from pymongo.asynchronous.change_stream import AsyncChangeStream, AsyncClusterChangeStream
6868
from pymongo.asynchronous.client_bulk import _AsyncClientBulk
@@ -121,6 +121,7 @@
121121
_handle_option_deprecations,
122122
_handle_security_options,
123123
_normalize_options,
124+
split_hosts,
124125
)
125126
from pymongo.write_concern import DEFAULT_WRITE_CONCERN, WriteConcern
126127

@@ -784,7 +785,7 @@ def __init__(
784785
# it must be a URI,
785786
# https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
786787
if "/" in entity:
787-
res = pymongo.asynchronous.uri_parser._validate_uri(
788+
res = pymongo.uri_parser_shared._validate_uri(
788789
entity,
789790
port,
790791
validate=True,
@@ -800,7 +801,7 @@ def __init__(
800801
opts = res["options"]
801802
fqdn = res["fqdn"]
802803
else:
803-
seeds.update(uri_parser_shared.split_hosts(entity, self._port))
804+
seeds.update(split_hosts(entity, self._port))
804805
if not seeds:
805806
raise ConfigurationError("need to specify at least one host")
806807

@@ -893,7 +894,7 @@ async def _resolve_srv(self) -> None:
893894
seeds.update(res["nodelist"])
894895
opts = res["options"]
895896
else:
896-
seeds.update(uri_parser_shared.split_hosts(entity, self._port))
897+
seeds.update(split_hosts(entity, self._port))
897898

898899
if not seeds:
899900
raise ConfigurationError("need to specify at least one host")

pymongo/asynchronous/srv_resolver.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ async def _resolve(*args: Any, **kwargs: Any) -> resolver.Answer:
5858
else:
5959
from dns import asyncresolver
6060

61-
return await asyncresolver.resolve(*args, **kwargs) # type:ignore[return-value]
61+
if hasattr(asyncresolver, "resolve"):
62+
# dnspython >= 2
63+
return await asyncresolver.resolve(*args, **kwargs) # type:ignore[return-value]
64+
raise ConfigurationError("Upgrade to dnspython version >= 2.0")
6265

6366

6467
_INVALID_HOST_MSG = (

pymongo/asynchronous/uri_parser.py

Lines changed: 2 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,17 @@
44
from typing import Any, Optional
55
from urllib.parse import unquote_plus
66

7-
from pymongo.asynchronous.srv_resolver import _have_dnspython, _SrvResolver
7+
from pymongo.asynchronous.srv_resolver import _SrvResolver
88
from pymongo.common import SRV_SERVICE_NAME, _CaseInsensitiveDictionary
99
from pymongo.errors import ConfigurationError, InvalidURI
1010
from pymongo.uri_parser_shared import (
1111
_ALLOWED_TXT_OPTS,
12-
_BAD_DB_CHARS,
1312
DEFAULT_PORT,
1413
SCHEME,
1514
SCHEME_LEN,
16-
SRV_SCHEME,
1715
SRV_SCHEME_LEN,
1816
_check_options,
19-
parse_userinfo,
17+
_validate_uri,
2018
split_hosts,
2119
split_options,
2220
)
@@ -103,102 +101,6 @@ async def parse_uri(
103101
return result
104102

105103

106-
def _validate_uri(
107-
uri: str,
108-
default_port: Optional[int] = DEFAULT_PORT,
109-
validate: bool = True,
110-
warn: bool = False,
111-
normalize: bool = True,
112-
srv_max_hosts: Optional[int] = None,
113-
) -> dict[str, Any]:
114-
if uri.startswith(SCHEME):
115-
is_srv = False
116-
scheme_free = uri[SCHEME_LEN:]
117-
elif uri.startswith(SRV_SCHEME):
118-
if not _have_dnspython():
119-
python_path = sys.executable or "python"
120-
raise ConfigurationError(
121-
'The "dnspython" module must be '
122-
"installed to use mongodb+srv:// URIs. "
123-
"To fix this error install pymongo again:\n "
124-
"%s -m pip install pymongo>=4.3" % (python_path)
125-
)
126-
is_srv = True
127-
scheme_free = uri[SRV_SCHEME_LEN:]
128-
else:
129-
raise InvalidURI(f"Invalid URI scheme: URI must begin with '{SCHEME}' or '{SRV_SCHEME}'")
130-
131-
if not scheme_free:
132-
raise InvalidURI("Must provide at least one hostname or IP")
133-
134-
user = None
135-
passwd = None
136-
dbase = None
137-
collection = None
138-
options = _CaseInsensitiveDictionary()
139-
140-
host_plus_db_part, _, opts = scheme_free.partition("?")
141-
if "/" in host_plus_db_part:
142-
host_part, _, dbase = host_plus_db_part.partition("/")
143-
else:
144-
host_part = host_plus_db_part
145-
146-
if dbase:
147-
dbase = unquote_plus(dbase)
148-
if "." in dbase:
149-
dbase, collection = dbase.split(".", 1)
150-
if _BAD_DB_CHARS.search(dbase):
151-
raise InvalidURI('Bad database name "%s"' % dbase)
152-
else:
153-
dbase = None
154-
155-
if opts:
156-
options.update(split_options(opts, validate, warn, normalize))
157-
if "@" in host_part:
158-
userinfo, _, hosts = host_part.rpartition("@")
159-
user, passwd = parse_userinfo(userinfo)
160-
else:
161-
hosts = host_part
162-
163-
if "/" in hosts:
164-
raise InvalidURI("Any '/' in a unix domain socket must be percent-encoded: %s" % host_part)
165-
166-
hosts = unquote_plus(hosts)
167-
fqdn = None
168-
srv_max_hosts = srv_max_hosts or options.get("srvMaxHosts")
169-
if is_srv:
170-
if options.get("directConnection"):
171-
raise ConfigurationError(f"Cannot specify directConnection=true with {SRV_SCHEME} URIs")
172-
nodes = split_hosts(hosts, default_port=None)
173-
if len(nodes) != 1:
174-
raise InvalidURI(f"{SRV_SCHEME} URIs must include one, and only one, hostname")
175-
fqdn, port = nodes[0]
176-
if port is not None:
177-
raise InvalidURI(f"{SRV_SCHEME} URIs must not include a port number")
178-
elif not is_srv and options.get("srvServiceName") is not None:
179-
raise ConfigurationError(
180-
"The srvServiceName option is only allowed with 'mongodb+srv://' URIs"
181-
)
182-
elif not is_srv and srv_max_hosts:
183-
raise ConfigurationError(
184-
"The srvMaxHosts option is only allowed with 'mongodb+srv://' URIs"
185-
)
186-
else:
187-
nodes = split_hosts(hosts, default_port=default_port)
188-
189-
_check_options(nodes, options)
190-
191-
return {
192-
"nodelist": nodes,
193-
"username": user,
194-
"password": passwd,
195-
"database": dbase,
196-
"collection": collection,
197-
"options": options,
198-
"fqdn": fqdn,
199-
}
200-
201-
202104
async def _parse_srv(
203105
uri: str,
204106
default_port: Optional[int] = DEFAULT_PORT,
@@ -277,10 +179,6 @@ async def _parse_srv(
277179
try:
278180
if _IS_SYNC:
279181
pprint.pprint(parse_uri(sys.argv[1])) # noqa: T203
280-
else:
281-
import asyncio
282-
283-
pprint.pprint(asyncio.run(parse_uri(sys.argv[1]))) # type:ignore[arg-type] # noqa: T203
284182
except InvalidURI as exc:
285183
print(exc) # noqa: T201
286184
sys.exit(0)

pymongo/synchronous/mongo_client.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,10 @@
5858
cast,
5959
)
6060

61-
import pymongo.synchronous.uri_parser
61+
import pymongo.uri_parser_shared
6262
from bson.codec_options import DEFAULT_CODEC_OPTIONS, CodecOptions, TypeRegistry
6363
from bson.timestamp import Timestamp
64-
from pymongo import _csot, common, helpers_shared, periodic_executor, uri_parser_shared
64+
from pymongo import _csot, common, helpers_shared, periodic_executor
6565
from pymongo.client_options import ClientOptions
6666
from pymongo.errors import (
6767
AutoReconnect,
@@ -120,6 +120,7 @@
120120
_handle_option_deprecations,
121121
_handle_security_options,
122122
_normalize_options,
123+
split_hosts,
123124
)
124125
from pymongo.write_concern import DEFAULT_WRITE_CONCERN, WriteConcern
125126

@@ -782,7 +783,7 @@ def __init__(
782783
# it must be a URI,
783784
# https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names
784785
if "/" in entity:
785-
res = pymongo.synchronous.uri_parser._validate_uri(
786+
res = pymongo.uri_parser_shared._validate_uri(
786787
entity,
787788
port,
788789
validate=True,
@@ -798,7 +799,7 @@ def __init__(
798799
opts = res["options"]
799800
fqdn = res["fqdn"]
800801
else:
801-
seeds.update(uri_parser_shared.split_hosts(entity, self._port))
802+
seeds.update(split_hosts(entity, self._port))
802803
if not seeds:
803804
raise ConfigurationError("need to specify at least one host")
804805

@@ -891,7 +892,7 @@ def _resolve_srv(self) -> None:
891892
seeds.update(res["nodelist"])
892893
opts = res["options"]
893894
else:
894-
seeds.update(uri_parser_shared.split_hosts(entity, self._port))
895+
seeds.update(split_hosts(entity, self._port))
895896

896897
if not seeds:
897898
raise ConfigurationError("need to specify at least one host")

pymongo/synchronous/srv_resolver.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ def _resolve(*args: Any, **kwargs: Any) -> resolver.Answer:
5858
else:
5959
from dns import asyncresolver
6060

61-
return asyncresolver.resolve(*args, **kwargs) # type:ignore[return-value]
61+
if hasattr(asyncresolver, "resolve"):
62+
# dnspython >= 2
63+
return asyncresolver.resolve(*args, **kwargs) # type:ignore[return-value]
64+
raise ConfigurationError("Upgrade to dnspython version >= 2.0")
6265

6366

6467
_INVALID_HOST_MSG = (

pymongo/synchronous/uri_parser.py

Lines changed: 2 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,15 @@
66

77
from pymongo.common import SRV_SERVICE_NAME, _CaseInsensitiveDictionary
88
from pymongo.errors import ConfigurationError, InvalidURI
9-
from pymongo.synchronous.srv_resolver import _have_dnspython, _SrvResolver
9+
from pymongo.synchronous.srv_resolver import _SrvResolver
1010
from pymongo.uri_parser_shared import (
1111
_ALLOWED_TXT_OPTS,
12-
_BAD_DB_CHARS,
1312
DEFAULT_PORT,
1413
SCHEME,
1514
SCHEME_LEN,
16-
SRV_SCHEME,
1715
SRV_SCHEME_LEN,
1816
_check_options,
19-
parse_userinfo,
17+
_validate_uri,
2018
split_hosts,
2119
split_options,
2220
)
@@ -103,102 +101,6 @@ def parse_uri(
103101
return result
104102

105103

106-
def _validate_uri(
107-
uri: str,
108-
default_port: Optional[int] = DEFAULT_PORT,
109-
validate: bool = True,
110-
warn: bool = False,
111-
normalize: bool = True,
112-
srv_max_hosts: Optional[int] = None,
113-
) -> dict[str, Any]:
114-
if uri.startswith(SCHEME):
115-
is_srv = False
116-
scheme_free = uri[SCHEME_LEN:]
117-
elif uri.startswith(SRV_SCHEME):
118-
if not _have_dnspython():
119-
python_path = sys.executable or "python"
120-
raise ConfigurationError(
121-
'The "dnspython" module must be '
122-
"installed to use mongodb+srv:// URIs. "
123-
"To fix this error install pymongo again:\n "
124-
"%s -m pip install pymongo>=4.3" % (python_path)
125-
)
126-
is_srv = True
127-
scheme_free = uri[SRV_SCHEME_LEN:]
128-
else:
129-
raise InvalidURI(f"Invalid URI scheme: URI must begin with '{SCHEME}' or '{SRV_SCHEME}'")
130-
131-
if not scheme_free:
132-
raise InvalidURI("Must provide at least one hostname or IP")
133-
134-
user = None
135-
passwd = None
136-
dbase = None
137-
collection = None
138-
options = _CaseInsensitiveDictionary()
139-
140-
host_plus_db_part, _, opts = scheme_free.partition("?")
141-
if "/" in host_plus_db_part:
142-
host_part, _, dbase = host_plus_db_part.partition("/")
143-
else:
144-
host_part = host_plus_db_part
145-
146-
if dbase:
147-
dbase = unquote_plus(dbase)
148-
if "." in dbase:
149-
dbase, collection = dbase.split(".", 1)
150-
if _BAD_DB_CHARS.search(dbase):
151-
raise InvalidURI('Bad database name "%s"' % dbase)
152-
else:
153-
dbase = None
154-
155-
if opts:
156-
options.update(split_options(opts, validate, warn, normalize))
157-
if "@" in host_part:
158-
userinfo, _, hosts = host_part.rpartition("@")
159-
user, passwd = parse_userinfo(userinfo)
160-
else:
161-
hosts = host_part
162-
163-
if "/" in hosts:
164-
raise InvalidURI("Any '/' in a unix domain socket must be percent-encoded: %s" % host_part)
165-
166-
hosts = unquote_plus(hosts)
167-
fqdn = None
168-
srv_max_hosts = srv_max_hosts or options.get("srvMaxHosts")
169-
if is_srv:
170-
if options.get("directConnection"):
171-
raise ConfigurationError(f"Cannot specify directConnection=true with {SRV_SCHEME} URIs")
172-
nodes = split_hosts(hosts, default_port=None)
173-
if len(nodes) != 1:
174-
raise InvalidURI(f"{SRV_SCHEME} URIs must include one, and only one, hostname")
175-
fqdn, port = nodes[0]
176-
if port is not None:
177-
raise InvalidURI(f"{SRV_SCHEME} URIs must not include a port number")
178-
elif not is_srv and options.get("srvServiceName") is not None:
179-
raise ConfigurationError(
180-
"The srvServiceName option is only allowed with 'mongodb+srv://' URIs"
181-
)
182-
elif not is_srv and srv_max_hosts:
183-
raise ConfigurationError(
184-
"The srvMaxHosts option is only allowed with 'mongodb+srv://' URIs"
185-
)
186-
else:
187-
nodes = split_hosts(hosts, default_port=default_port)
188-
189-
_check_options(nodes, options)
190-
191-
return {
192-
"nodelist": nodes,
193-
"username": user,
194-
"password": passwd,
195-
"database": dbase,
196-
"collection": collection,
197-
"options": options,
198-
"fqdn": fqdn,
199-
}
200-
201-
202104
def _parse_srv(
203105
uri: str,
204106
default_port: Optional[int] = DEFAULT_PORT,
@@ -277,10 +179,6 @@ def _parse_srv(
277179
try:
278180
if _IS_SYNC:
279181
pprint.pprint(parse_uri(sys.argv[1])) # noqa: T203
280-
else:
281-
import asyncio
282-
283-
pprint.pprint(asyncio.run(parse_uri(sys.argv[1]))) # type:ignore[arg-type] # noqa: T203
284182
except InvalidURI as exc:
285183
print(exc) # noqa: T201
286184
sys.exit(0)

0 commit comments

Comments
 (0)