Skip to content

Commit 52ed5a4

Browse files
authored
PYTHON-3052 Add Typings to PyMongo Itself (mongodb#829)
1 parent c760f90 commit 52ed5a4

31 files changed

+617
-534
lines changed

.github/workflows/test-python.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,24 @@ jobs:
2626
- name: Run tests
2727
run: |
2828
python setup.py test
29+
30+
mypytest:
31+
name: Run mypy
32+
runs-on: ubuntu-latest
33+
strategy:
34+
matrix:
35+
python-version: ['3.7', '3.10']
36+
fail-fast: false
37+
steps:
38+
- uses: actions/checkout@v2
39+
- name: Set up Python ${{ matrix.python-version }}
40+
uses: actions/setup-python@v2
41+
with:
42+
python-version: ${{ matrix.python-version }}
43+
- name: Install dependencies
44+
run: |
45+
python -m pip install -U pip mypy
46+
pip install -e ".[zstd, srv]"
47+
- name: Run mypy
48+
run: |
49+
mypy --install-types --non-interactive bson gridfs tools

bson/__init__.py

Lines changed: 105 additions & 96 deletions
Large diffs are not rendered by default.

bson/_helpers.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,23 @@
1515
"""Setstate and getstate functions for objects with __slots__, allowing
1616
compatibility with default pickling protocol
1717
"""
18+
from typing import Any, Mapping
1819

1920

20-
def _setstate_slots(self, state):
21+
def _setstate_slots(self: Any, state: Any) -> None:
2122
for slot, value in state.items():
2223
setattr(self, slot, value)
2324

2425

25-
def _mangle_name(name, prefix):
26+
def _mangle_name(name: str, prefix: str) -> str:
2627
if name.startswith("__"):
2728
prefix = "_"+prefix
2829
else:
2930
prefix = ""
3031
return prefix + name
3132

3233

33-
def _getstate_slots(self):
34+
def _getstate_slots(self: Any) -> Mapping[Any, Any]:
3435
prefix = self.__class__.__name__
3536
ret = dict()
3637
for name in self.__slots__:

bson/binary.py

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

15+
from typing import Any, Tuple, Type
1516
from uuid import UUID
16-
from warnings import warn
1717

1818
"""Tools for representing BSON binary data.
1919
"""
@@ -69,7 +69,7 @@ class UuidRepresentation:
6969
code. When decoding a BSON binary field with a UUID subtype, a
7070
:class:`~bson.binary.Binary` instance will be returned instead of a
7171
:class:`uuid.UUID` instance.
72-
72+
7373
See :ref:`unspecified-representation-details` for details.
7474
7575
.. versionadded:: 3.11
@@ -81,7 +81,7 @@ class UuidRepresentation:
8181
:class:`uuid.UUID` instances will automatically be encoded to
8282
and decoded from BSON binary, using RFC-4122 byte order with
8383
binary subtype :data:`UUID_SUBTYPE`.
84-
84+
8585
See :ref:`standard-representation-details` for details.
8686
8787
.. versionadded:: 3.11
@@ -93,7 +93,7 @@ class UuidRepresentation:
9393
:class:`uuid.UUID` instances will automatically be encoded to
9494
and decoded from BSON binary, using RFC-4122 byte order with
9595
binary subtype :data:`OLD_UUID_SUBTYPE`.
96-
96+
9797
See :ref:`python-legacy-representation-details` for details.
9898
9999
.. versionadded:: 3.11
@@ -105,7 +105,7 @@ class UuidRepresentation:
105105
:class:`uuid.UUID` instances will automatically be encoded to
106106
and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`,
107107
using the Java driver's legacy byte order.
108-
108+
109109
See :ref:`java-legacy-representation-details` for details.
110110
111111
.. versionadded:: 3.11
@@ -117,7 +117,7 @@ class UuidRepresentation:
117117
:class:`uuid.UUID` instances will automatically be encoded to
118118
and decoded from BSON binary subtype :data:`OLD_UUID_SUBTYPE`,
119119
using the C# driver's legacy byte order.
120-
120+
121121
See :ref:`csharp-legacy-representation-details` for details.
122122
123123
.. versionadded:: 3.11
@@ -153,11 +153,12 @@ class UuidRepresentation:
153153
"""
154154

155155
ALL_UUID_SUBTYPES = (OLD_UUID_SUBTYPE, UUID_SUBTYPE)
156-
ALL_UUID_REPRESENTATIONS = (UuidRepresentation.UNSPECIFIED,
157-
UuidRepresentation.STANDARD,
158-
UuidRepresentation.PYTHON_LEGACY,
159-
UuidRepresentation.JAVA_LEGACY,
160-
UuidRepresentation.CSHARP_LEGACY)
156+
ALL_UUID_REPRESENTATIONS = (
157+
UuidRepresentation.UNSPECIFIED,
158+
UuidRepresentation.STANDARD,
159+
UuidRepresentation.PYTHON_LEGACY,
160+
UuidRepresentation.JAVA_LEGACY,
161+
UuidRepresentation.CSHARP_LEGACY)
161162
UUID_REPRESENTATION_NAMES = {
162163
UuidRepresentation.UNSPECIFIED: 'UuidRepresentation.UNSPECIFIED',
163164
UuidRepresentation.STANDARD: 'UuidRepresentation.STANDARD',
@@ -208,8 +209,9 @@ class Binary(bytes):
208209
"""
209210

210211
_type_marker = 5
212+
__subtype: int
211213

212-
def __new__(cls, data, subtype=BINARY_SUBTYPE):
214+
def __new__(cls: Type["Binary"], data: bytes, subtype: int = BINARY_SUBTYPE) -> "Binary":
213215
if not isinstance(subtype, int):
214216
raise TypeError("subtype must be an instance of int")
215217
if subtype >= 256 or subtype < 0:
@@ -220,7 +222,7 @@ def __new__(cls, data, subtype=BINARY_SUBTYPE):
220222
return self
221223

222224
@classmethod
223-
def from_uuid(cls, uuid, uuid_representation=UuidRepresentation.STANDARD):
225+
def from_uuid(cls: Type["Binary"], uuid: UUID, uuid_representation: int = UuidRepresentation.STANDARD) -> "Binary":
224226
"""Create a BSON Binary object from a Python UUID.
225227
226228
Creates a :class:`~bson.binary.Binary` object from a
@@ -271,7 +273,7 @@ def from_uuid(cls, uuid, uuid_representation=UuidRepresentation.STANDARD):
271273

272274
return cls(payload, subtype)
273275

274-
def as_uuid(self, uuid_representation=UuidRepresentation.STANDARD):
276+
def as_uuid(self, uuid_representation: int = UuidRepresentation.STANDARD) -> UUID:
275277
"""Create a Python UUID from this BSON Binary object.
276278
277279
Decodes this binary object as a native :class:`uuid.UUID` instance
@@ -316,19 +318,19 @@ def as_uuid(self, uuid_representation=UuidRepresentation.STANDARD):
316318
self.subtype, UUID_REPRESENTATION_NAMES[uuid_representation]))
317319

318320
@property
319-
def subtype(self):
321+
def subtype(self) -> int:
320322
"""Subtype of this binary data.
321323
"""
322324
return self.__subtype
323325

324-
def __getnewargs__(self):
326+
def __getnewargs__(self) -> Tuple[bytes, int]: # type: ignore[override]
325327
# Work around http://bugs.python.org/issue7382
326328
data = super(Binary, self).__getnewargs__()[0]
327329
if not isinstance(data, bytes):
328330
data = data.encode('latin-1')
329331
return data, self.__subtype
330332

331-
def __eq__(self, other):
333+
def __eq__(self, other : Any) -> bool:
332334
if isinstance(other, Binary):
333335
return ((self.__subtype, bytes(self)) ==
334336
(other.subtype, bytes(other)))
@@ -337,10 +339,10 @@ def __eq__(self, other):
337339
# subclass of str...
338340
return False
339341

340-
def __hash__(self):
342+
def __hash__(self) -> int:
341343
return super(Binary, self).__hash__() ^ hash(self.__subtype)
342344

343-
def __ne__(self, other):
345+
def __ne__(self, other: Any) -> bool:
344346
return not self == other
345347

346348
def __repr__(self):

bson/code.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"""
1717

1818
from collections.abc import Mapping as _Mapping
19+
from typing import Any, Mapping, Optional, Type, Union
1920

2021

2122
class Code(str):
@@ -47,49 +48,50 @@ class Code(str):
4748
"""
4849

4950
_type_marker = 13
51+
__scope: Union[Mapping[str, Any], None]
5052

51-
def __new__(cls, code, scope=None, **kwargs):
53+
def __new__(cls: Type["Code"], code: Union[str, "Code"], scope: Optional[Mapping[str, Any]] = None, **kwargs: Any) -> "Code":
5254
if not isinstance(code, str):
5355
raise TypeError("code must be an instance of str")
5456

5557
self = str.__new__(cls, code)
5658

5759
try:
58-
self.__scope = code.scope
60+
self.__scope = code.scope # type: ignore
5961
except AttributeError:
6062
self.__scope = None
6163

6264
if scope is not None:
6365
if not isinstance(scope, _Mapping):
6466
raise TypeError("scope must be an instance of dict")
6567
if self.__scope is not None:
66-
self.__scope.update(scope)
68+
self.__scope.update(scope) # type: ignore
6769
else:
6870
self.__scope = scope
6971

7072
if kwargs:
7173
if self.__scope is not None:
72-
self.__scope.update(kwargs)
74+
self.__scope.update(kwargs) # type: ignore
7375
else:
7476
self.__scope = kwargs
7577

7678
return self
7779

7880
@property
79-
def scope(self):
81+
def scope(self) -> Optional[Mapping[str, Any]]:
8082
"""Scope dictionary for this instance or ``None``.
8183
"""
8284
return self.__scope
8385

8486
def __repr__(self):
8587
return "Code(%s, %r)" % (str.__repr__(self), self.__scope)
8688

87-
def __eq__(self, other):
89+
def __eq__(self, other: Any) -> bool:
8890
if isinstance(other, Code):
8991
return (self.__scope, str(self)) == (other.__scope, str(other))
9092
return False
9193

92-
__hash__ = None
94+
__hash__: Any = None
9395

94-
def __ne__(self, other):
96+
def __ne__(self, other: Any) -> bool:
9597
return not self == other

0 commit comments

Comments
 (0)