Skip to content

Commit b40f13b

Browse files
authored
PYTHON-3311 Module "pymongo" does not explicitly export attribute "MongoClient"; implicit reexport disabled (#994)
1 parent c09af58 commit b40f13b

File tree

7 files changed

+184
-19
lines changed

7 files changed

+184
-19
lines changed

bson/__init__.py

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686
cast,
8787
)
8888

89-
from bson.binary import ( # noqa: F401
89+
from bson.binary import (
9090
ALL_UUID_SUBTYPES,
9191
CSHARP_LEGACY,
9292
JAVA_LEGACY,
@@ -128,6 +128,66 @@
128128
except ImportError:
129129
_USE_C = False
130130

131+
__all__ = [
132+
"ALL_UUID_SUBTYPES",
133+
"CSHARP_LEGACY",
134+
"JAVA_LEGACY",
135+
"OLD_UUID_SUBTYPE",
136+
"STANDARD",
137+
"UUID_SUBTYPE",
138+
"Binary",
139+
"UuidRepresentation",
140+
"Code",
141+
"DEFAULT_CODEC_OPTIONS",
142+
"CodecOptions",
143+
"DBRef",
144+
"Decimal128",
145+
"InvalidBSON",
146+
"InvalidDocument",
147+
"InvalidStringData",
148+
"Int64",
149+
"MaxKey",
150+
"MinKey",
151+
"ObjectId",
152+
"Regex",
153+
"RE_TYPE",
154+
"SON",
155+
"Timestamp",
156+
"utc",
157+
"EPOCH_AWARE",
158+
"EPOCH_NAIVE",
159+
"BSONNUM",
160+
"BSONSTR",
161+
"BSONOBJ",
162+
"BSONARR",
163+
"BSONBIN",
164+
"BSONUND",
165+
"BSONOID",
166+
"BSONBOO",
167+
"BSONDAT",
168+
"BSONNUL",
169+
"BSONRGX",
170+
"BSONREF",
171+
"BSONCOD",
172+
"BSONSYM",
173+
"BSONCWS",
174+
"BSONINT",
175+
"BSONTIM",
176+
"BSONLON",
177+
"BSONDEC",
178+
"BSONMIN",
179+
"BSONMAX",
180+
"get_data_and_view",
181+
"gen_list_name",
182+
"encode",
183+
"decode",
184+
"decode_all",
185+
"decode_iter",
186+
"decode_file_iter",
187+
"is_valid",
188+
"BSON",
189+
"has_c",
190+
]
131191

132192
EPOCH_AWARE = datetime.datetime.fromtimestamp(0, utc)
133193
EPOCH_NAIVE = datetime.datetime.utcfromtimestamp(0)

bson/objectid.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
"""Tools for working with MongoDB `ObjectIds
16-
<http://dochub.mongodb.org/core/objectids>`_.
15+
"""Tools for working with MongoDB ObjectIds.
1716
"""
1817

1918
import binascii
@@ -88,7 +87,7 @@ def __init__(self, oid: Optional[Union[str, "ObjectId", bytes]] = None) -> None:
8887
:Parameters:
8988
- `oid` (optional): a valid ObjectId.
9089
91-
.. seealso:: The MongoDB documentation on `ObjectIds`_.
90+
.. seealso:: The MongoDB documentation on `ObjectIds <http://dochub.mongodb.org/core/objectids>`_.
9291
9392
.. versionchanged:: 3.8
9493
:class:`~bson.objectid.ObjectId` now implements the `ObjectID

gridfs/__init__.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@
4242
from pymongo.read_preferences import _ServerMode
4343
from pymongo.write_concern import WriteConcern
4444

45+
__all__ = [
46+
"GridFS",
47+
"GridFSBucket",
48+
"NoFile",
49+
"DEFAULT_CHUNK_SIZE",
50+
"GridIn",
51+
"GridOut",
52+
"GridOutCursor",
53+
]
54+
4555

4656
class GridFS(object):
4757
"""An instance of GridFS on top of a single Database."""

pymongo/__init__.py

Lines changed: 36 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,35 @@
1616

1717
from typing import ContextManager, Optional, Tuple, Union
1818

19+
__all__ = [
20+
"ASCENDING",
21+
"DESCENDING",
22+
"GEO2D",
23+
"GEOSPHERE",
24+
"HASHED",
25+
"TEXT",
26+
"version_tuple",
27+
"get_version_string",
28+
"__version__",
29+
"version",
30+
"ReturnDocument",
31+
"MAX_SUPPORTED_WIRE_VERSION",
32+
"MIN_SUPPORTED_WIRE_VERSION",
33+
"CursorType",
34+
"MongoClient",
35+
"DeleteMany",
36+
"DeleteOne",
37+
"IndexModel",
38+
"InsertOne",
39+
"ReplaceOne",
40+
"UpdateMany",
41+
"UpdateOne",
42+
"ReadPreference",
43+
"WriteConcern",
44+
"has_c",
45+
"timeout",
46+
]
47+
1948
ASCENDING = 1
2049
"""Ascending sort order."""
2150
DESCENDING = -1
@@ -70,14 +99,11 @@ def get_version_string() -> str:
7099
"""Current version of PyMongo."""
71100

72101
from pymongo import _csot
73-
from pymongo.collection import ReturnDocument # noqa: F401
74-
from pymongo.common import ( # noqa: F401
75-
MAX_SUPPORTED_WIRE_VERSION,
76-
MIN_SUPPORTED_WIRE_VERSION,
77-
)
78-
from pymongo.cursor import CursorType # noqa: F401
79-
from pymongo.mongo_client import MongoClient # noqa: F401
80-
from pymongo.operations import ( # noqa: F401
102+
from pymongo.collection import ReturnDocument
103+
from pymongo.common import MAX_SUPPORTED_WIRE_VERSION, MIN_SUPPORTED_WIRE_VERSION
104+
from pymongo.cursor import CursorType
105+
from pymongo.mongo_client import MongoClient
106+
from pymongo.operations import (
81107
DeleteMany,
82108
DeleteOne,
83109
IndexModel,
@@ -86,8 +112,8 @@ def get_version_string() -> str:
86112
UpdateMany,
87113
UpdateOne,
88114
)
89-
from pymongo.read_preferences import ReadPreference # noqa: F401
90-
from pymongo.write_concern import WriteConcern # noqa: F401
115+
from pymongo.read_preferences import ReadPreference
116+
from pymongo.write_concern import WriteConcern
91117

92118

93119
def has_c() -> bool:

pymongo/database.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ def _check_name(name):
5555

5656

5757
if TYPE_CHECKING:
58+
import bson.codec_options
5859
from pymongo.client_session import ClientSession
5960
from pymongo.mongo_client import MongoClient
6061
from pymongo.read_concern import ReadConcern
@@ -699,7 +700,7 @@ def command(
699700
check: bool = True,
700701
allowable_errors: Optional[Sequence[Union[str, int]]] = None,
701702
read_preference: Optional[_ServerMode] = None,
702-
codec_options: "Optional[CodecOptions[_CodecDocumentType]]" = None,
703+
codec_options: "Optional[bson.codec_options.CodecOptions[_CodecDocumentType]]" = None,
703704
session: Optional["ClientSession"] = None,
704705
comment: Optional[Any] = None,
705706
**kwargs: Any,
@@ -764,7 +765,7 @@ def command(
764765
765766
.. note:: :meth:`command` does **not** obey this Database's
766767
:attr:`read_preference` or :attr:`codec_options`. You must use the
767-
`read_preference` and `codec_options` parameters instead.
768+
``read_preference`` and ``codec_options`` parameters instead.
768769
769770
.. note:: :meth:`command` does **not** apply any custom TypeDecoders
770771
when decoding the command response.
@@ -785,7 +786,7 @@ def command(
785786
regular expressions as :class:`~bson.regex.Regex` objects. Use
786787
:meth:`~bson.regex.Regex.try_compile` to attempt to convert from a
787788
BSON regular expression to a Python regular expression object.
788-
Added the `codec_options` parameter.
789+
Added the ``codec_options`` parameter.
789790
790791
.. seealso:: The MongoDB documentation on `commands <https://dochub.mongodb.org/core/commands>`_.
791792
"""

test/test_default_exports.py

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
# Copyright 2022-present MongoDB, Inc.
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
"""Test the default exports of the top level packages."""
16+
import inspect
17+
import unittest
18+
19+
import bson
20+
import gridfs
21+
import pymongo
22+
23+
BSON_IGNORE = []
24+
GRIDFS_IGNORE = [
25+
"ASCENDING",
26+
"DESCENDING",
27+
"ClientSession",
28+
"Collection",
29+
"ObjectId",
30+
"validate_string",
31+
"Database",
32+
"ConfigurationError",
33+
"WriteConcern",
34+
]
35+
PYMONGO_IGNORE = []
36+
GLOBAL_INGORE = ["TYPE_CHECKING"]
37+
38+
39+
class TestDefaultExports(unittest.TestCase):
40+
def check_module(self, mod, ignores):
41+
names = dir(mod)
42+
names.remove("__all__")
43+
for name in mod.__all__:
44+
if name not in names and name not in ignores:
45+
self.fail(f"{name} was included in {mod}.__all__ but is not a valid symbol")
46+
47+
for name in names:
48+
if name not in mod.__all__ and name not in ignores:
49+
if name in GLOBAL_INGORE:
50+
continue
51+
value = getattr(mod, name)
52+
if inspect.ismodule(value):
53+
continue
54+
if getattr(value, "__module__", None) == "typing":
55+
continue
56+
if not name.startswith("_"):
57+
self.fail(f"{name} was not included in {mod}.__all__")
58+
59+
def test_pymongo(self):
60+
self.check_module(pymongo, PYMONGO_IGNORE)
61+
62+
def test_gridfs(self):
63+
self.check_module(gridfs, GRIDFS_IGNORE)
64+
65+
def test_bson(self):
66+
self.check_module(bson, BSON_IGNORE)
67+
68+
69+
if __name__ == "__main__":
70+
unittest.main()

test/test_mypy.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,9 +43,8 @@ class Movie(TypedDict): # type: ignore[misc]
4343
from bson import CodecOptions, decode, decode_all, decode_file_iter, decode_iter, encode
4444
from bson.raw_bson import RawBSONDocument
4545
from bson.son import SON
46-
from pymongo import ASCENDING
46+
from pymongo import ASCENDING, MongoClient
4747
from pymongo.collection import Collection
48-
from pymongo.mongo_client import MongoClient
4948
from pymongo.operations import InsertOne
5049
from pymongo.read_preferences import ReadPreference
5150

0 commit comments

Comments
 (0)