sensu-plugins-mongodb-mrtrotl 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +1 -0
- data/LICENSE +22 -0
- data/README.md +27 -0
- data/bin/check-mongodb-metric.rb +144 -0
- data/bin/check-mongodb-query-count.rb +267 -0
- data/bin/check-mongodb.py +1644 -0
- data/bin/check-mongodb.rb +5 -0
- data/bin/metrics-mongodb-replication.rb +254 -0
- data/bin/metrics-mongodb.rb +133 -0
- data/lib/bson/__init__.py +1347 -0
- data/lib/bson/__pycache__/__init__.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/_helpers.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/binary.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/code.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/codec_options.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/dbref.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/decimal128.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/errors.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/int64.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/json_util.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/max_key.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/min_key.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/objectid.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/raw_bson.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/regex.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/son.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/timestamp.cpython-310.pyc +0 -0
- data/lib/bson/__pycache__/tz_util.cpython-310.pyc +0 -0
- data/lib/bson/_cbson.cpython-310-x86_64-linux-gnu.so +0 -0
- data/lib/bson/_helpers.py +41 -0
- data/lib/bson/binary.py +364 -0
- data/lib/bson/code.py +101 -0
- data/lib/bson/codec_options.py +414 -0
- data/lib/bson/codec_options.pyi +100 -0
- data/lib/bson/dbref.py +133 -0
- data/lib/bson/decimal128.py +314 -0
- data/lib/bson/errors.py +35 -0
- data/lib/bson/int64.py +39 -0
- data/lib/bson/json_util.py +874 -0
- data/lib/bson/max_key.py +55 -0
- data/lib/bson/min_key.py +55 -0
- data/lib/bson/objectid.py +286 -0
- data/lib/bson/py.typed +2 -0
- data/lib/bson/raw_bson.py +175 -0
- data/lib/bson/regex.py +135 -0
- data/lib/bson/son.py +208 -0
- data/lib/bson/timestamp.py +124 -0
- data/lib/bson/tz_util.py +52 -0
- data/lib/gridfs/__init__.py +1015 -0
- data/lib/gridfs/__pycache__/__init__.cpython-310.pyc +0 -0
- data/lib/gridfs/__pycache__/errors.cpython-310.pyc +0 -0
- data/lib/gridfs/__pycache__/grid_file.cpython-310.pyc +0 -0
- data/lib/gridfs/errors.py +33 -0
- data/lib/gridfs/grid_file.py +907 -0
- data/lib/gridfs/py.typed +2 -0
- data/lib/pymongo/__init__.py +185 -0
- data/lib/pymongo/__pycache__/__init__.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/_csot.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/aggregation.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/auth.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/auth_aws.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/bulk.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/change_stream.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/client_options.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/client_session.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/collation.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/collection.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/command_cursor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/common.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/compression_support.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/cursor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/daemon.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/database.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/driver_info.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/encryption.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/encryption_options.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/errors.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/event_loggers.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/hello.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/helpers.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/max_staleness_selectors.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/message.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/mongo_client.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/monitor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/monitoring.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/network.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ocsp_cache.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ocsp_support.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/operations.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/periodic_executor.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/pool.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/pyopenssl_context.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/read_concern.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/read_preferences.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/response.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/results.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/saslprep.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_api.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_description.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_selectors.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/server_type.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/settings.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/socket_checker.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/srv_resolver.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ssl_context.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/ssl_support.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/topology.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/topology_description.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/typings.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/uri_parser.cpython-310.pyc +0 -0
- data/lib/pymongo/__pycache__/write_concern.cpython-310.pyc +0 -0
- data/lib/pymongo/_cmessage.cpython-310-x86_64-linux-gnu.so +0 -0
- data/lib/pymongo/_csot.py +118 -0
- data/lib/pymongo/aggregation.py +229 -0
- data/lib/pymongo/auth.py +549 -0
- data/lib/pymongo/auth_aws.py +94 -0
- data/lib/pymongo/bulk.py +513 -0
- data/lib/pymongo/change_stream.py +457 -0
- data/lib/pymongo/client_options.py +302 -0
- data/lib/pymongo/client_session.py +1112 -0
- data/lib/pymongo/collation.py +224 -0
- data/lib/pymongo/collection.py +3204 -0
- data/lib/pymongo/command_cursor.py +353 -0
- data/lib/pymongo/common.py +984 -0
- data/lib/pymongo/compression_support.py +149 -0
- data/lib/pymongo/cursor.py +1345 -0
- data/lib/pymongo/daemon.py +141 -0
- data/lib/pymongo/database.py +1202 -0
- data/lib/pymongo/driver_info.py +42 -0
- data/lib/pymongo/encryption.py +884 -0
- data/lib/pymongo/encryption_options.py +221 -0
- data/lib/pymongo/errors.py +365 -0
- data/lib/pymongo/event_loggers.py +221 -0
- data/lib/pymongo/hello.py +219 -0
- data/lib/pymongo/helpers.py +259 -0
- data/lib/pymongo/max_staleness_selectors.py +114 -0
- data/lib/pymongo/message.py +1440 -0
- data/lib/pymongo/mongo_client.py +2144 -0
- data/lib/pymongo/monitor.py +440 -0
- data/lib/pymongo/monitoring.py +1801 -0
- data/lib/pymongo/network.py +311 -0
- data/lib/pymongo/ocsp_cache.py +87 -0
- data/lib/pymongo/ocsp_support.py +372 -0
- data/lib/pymongo/operations.py +507 -0
- data/lib/pymongo/periodic_executor.py +183 -0
- data/lib/pymongo/pool.py +1660 -0
- data/lib/pymongo/py.typed +2 -0
- data/lib/pymongo/pyopenssl_context.py +383 -0
- data/lib/pymongo/read_concern.py +75 -0
- data/lib/pymongo/read_preferences.py +609 -0
- data/lib/pymongo/response.py +109 -0
- data/lib/pymongo/results.py +217 -0
- data/lib/pymongo/saslprep.py +113 -0
- data/lib/pymongo/server.py +247 -0
- data/lib/pymongo/server_api.py +170 -0
- data/lib/pymongo/server_description.py +285 -0
- data/lib/pymongo/server_selectors.py +153 -0
- data/lib/pymongo/server_type.py +32 -0
- data/lib/pymongo/settings.py +159 -0
- data/lib/pymongo/socket_checker.py +104 -0
- data/lib/pymongo/srv_resolver.py +126 -0
- data/lib/pymongo/ssl_context.py +39 -0
- data/lib/pymongo/ssl_support.py +99 -0
- data/lib/pymongo/topology.py +890 -0
- data/lib/pymongo/topology_description.py +639 -0
- data/lib/pymongo/typings.py +39 -0
- data/lib/pymongo/uri_parser.py +624 -0
- data/lib/pymongo/write_concern.py +129 -0
- data/lib/pymongo-4.2.0.dist-info/INSTALLER +1 -0
- data/lib/pymongo-4.2.0.dist-info/LICENSE +201 -0
- data/lib/pymongo-4.2.0.dist-info/METADATA +250 -0
- data/lib/pymongo-4.2.0.dist-info/RECORD +167 -0
- data/lib/pymongo-4.2.0.dist-info/REQUESTED +0 -0
- data/lib/pymongo-4.2.0.dist-info/WHEEL +6 -0
- data/lib/pymongo-4.2.0.dist-info/top_level.txt +3 -0
- data/lib/sensu-plugins-mongodb/metrics.rb +391 -0
- data/lib/sensu-plugins-mongodb/version.rb +9 -0
- data/lib/sensu-plugins-mongodb.rb +1 -0
- metadata +407 -0
@@ -0,0 +1,414 @@
|
|
1
|
+
# Copyright 2014-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
|
+
"""Tools for specifying BSON codec options."""
|
16
|
+
|
17
|
+
import abc
|
18
|
+
import datetime
|
19
|
+
from collections.abc import MutableMapping as _MutableMapping
|
20
|
+
from typing import (
|
21
|
+
Any,
|
22
|
+
Callable,
|
23
|
+
Dict,
|
24
|
+
Iterable,
|
25
|
+
Mapping,
|
26
|
+
NamedTuple,
|
27
|
+
Optional,
|
28
|
+
Type,
|
29
|
+
TypeVar,
|
30
|
+
Union,
|
31
|
+
cast,
|
32
|
+
)
|
33
|
+
|
34
|
+
from bson.binary import (
|
35
|
+
ALL_UUID_REPRESENTATIONS,
|
36
|
+
UUID_REPRESENTATION_NAMES,
|
37
|
+
UuidRepresentation,
|
38
|
+
)
|
39
|
+
|
40
|
+
|
41
|
+
def _abstractproperty(func: Callable[..., Any]) -> property:
|
42
|
+
return property(abc.abstractmethod(func))
|
43
|
+
|
44
|
+
|
45
|
+
_RAW_BSON_DOCUMENT_MARKER = 101
|
46
|
+
|
47
|
+
|
48
|
+
def _raw_document_class(document_class: Any) -> bool:
|
49
|
+
"""Determine if a document_class is a RawBSONDocument class."""
|
50
|
+
marker = getattr(document_class, "_type_marker", None)
|
51
|
+
return marker == _RAW_BSON_DOCUMENT_MARKER
|
52
|
+
|
53
|
+
|
54
|
+
class TypeEncoder(abc.ABC):
|
55
|
+
"""Base class for defining type codec classes which describe how a
|
56
|
+
custom type can be transformed to one of the types BSON understands.
|
57
|
+
|
58
|
+
Codec classes must implement the ``python_type`` attribute, and the
|
59
|
+
``transform_python`` method to support encoding.
|
60
|
+
|
61
|
+
See :ref:`custom-type-type-codec` documentation for an example.
|
62
|
+
"""
|
63
|
+
|
64
|
+
@_abstractproperty
|
65
|
+
def python_type(self) -> Any:
|
66
|
+
"""The Python type to be converted into something serializable."""
|
67
|
+
pass
|
68
|
+
|
69
|
+
@abc.abstractmethod
|
70
|
+
def transform_python(self, value: Any) -> Any:
|
71
|
+
"""Convert the given Python object into something serializable."""
|
72
|
+
pass
|
73
|
+
|
74
|
+
|
75
|
+
class TypeDecoder(abc.ABC):
|
76
|
+
"""Base class for defining type codec classes which describe how a
|
77
|
+
BSON type can be transformed to a custom type.
|
78
|
+
|
79
|
+
Codec classes must implement the ``bson_type`` attribute, and the
|
80
|
+
``transform_bson`` method to support decoding.
|
81
|
+
|
82
|
+
See :ref:`custom-type-type-codec` documentation for an example.
|
83
|
+
"""
|
84
|
+
|
85
|
+
@_abstractproperty
|
86
|
+
def bson_type(self) -> Any:
|
87
|
+
"""The BSON type to be converted into our own type."""
|
88
|
+
pass
|
89
|
+
|
90
|
+
@abc.abstractmethod
|
91
|
+
def transform_bson(self, value: Any) -> Any:
|
92
|
+
"""Convert the given BSON value into our own type."""
|
93
|
+
pass
|
94
|
+
|
95
|
+
|
96
|
+
class TypeCodec(TypeEncoder, TypeDecoder):
|
97
|
+
"""Base class for defining type codec classes which describe how a
|
98
|
+
custom type can be transformed to/from one of the types :mod:`bson`
|
99
|
+
can already encode/decode.
|
100
|
+
|
101
|
+
Codec classes must implement the ``python_type`` attribute, and the
|
102
|
+
``transform_python`` method to support encoding, as well as the
|
103
|
+
``bson_type`` attribute, and the ``transform_bson`` method to support
|
104
|
+
decoding.
|
105
|
+
|
106
|
+
See :ref:`custom-type-type-codec` documentation for an example.
|
107
|
+
"""
|
108
|
+
|
109
|
+
pass
|
110
|
+
|
111
|
+
|
112
|
+
_Codec = Union[TypeEncoder, TypeDecoder, TypeCodec]
|
113
|
+
_Fallback = Callable[[Any], Any]
|
114
|
+
_DocumentType = TypeVar("_DocumentType", bound=Mapping[str, Any])
|
115
|
+
|
116
|
+
|
117
|
+
class TypeRegistry(object):
|
118
|
+
"""Encapsulates type codecs used in encoding and / or decoding BSON, as
|
119
|
+
well as the fallback encoder. Type registries cannot be modified after
|
120
|
+
instantiation.
|
121
|
+
|
122
|
+
``TypeRegistry`` can be initialized with an iterable of type codecs, and
|
123
|
+
a callable for the fallback encoder::
|
124
|
+
|
125
|
+
>>> from bson.codec_options import TypeRegistry
|
126
|
+
>>> type_registry = TypeRegistry([Codec1, Codec2, Codec3, ...],
|
127
|
+
... fallback_encoder)
|
128
|
+
|
129
|
+
See :ref:`custom-type-type-registry` documentation for an example.
|
130
|
+
|
131
|
+
:Parameters:
|
132
|
+
- `type_codecs` (optional): iterable of type codec instances. If
|
133
|
+
``type_codecs`` contains multiple codecs that transform a single
|
134
|
+
python or BSON type, the transformation specified by the type codec
|
135
|
+
occurring last prevails. A TypeError will be raised if one or more
|
136
|
+
type codecs modify the encoding behavior of a built-in :mod:`bson`
|
137
|
+
type.
|
138
|
+
- `fallback_encoder` (optional): callable that accepts a single,
|
139
|
+
unencodable python value and transforms it into a type that
|
140
|
+
:mod:`bson` can encode. See :ref:`fallback-encoder-callable`
|
141
|
+
documentation for an example.
|
142
|
+
"""
|
143
|
+
|
144
|
+
def __init__(
|
145
|
+
self,
|
146
|
+
type_codecs: Optional[Iterable[_Codec]] = None,
|
147
|
+
fallback_encoder: Optional[_Fallback] = None,
|
148
|
+
) -> None:
|
149
|
+
self.__type_codecs = list(type_codecs or [])
|
150
|
+
self._fallback_encoder = fallback_encoder
|
151
|
+
self._encoder_map: Dict[Any, Any] = {}
|
152
|
+
self._decoder_map: Dict[Any, Any] = {}
|
153
|
+
|
154
|
+
if self._fallback_encoder is not None:
|
155
|
+
if not callable(fallback_encoder):
|
156
|
+
raise TypeError("fallback_encoder %r is not a callable" % (fallback_encoder))
|
157
|
+
|
158
|
+
for codec in self.__type_codecs:
|
159
|
+
is_valid_codec = False
|
160
|
+
if isinstance(codec, TypeEncoder):
|
161
|
+
self._validate_type_encoder(codec)
|
162
|
+
is_valid_codec = True
|
163
|
+
self._encoder_map[codec.python_type] = codec.transform_python
|
164
|
+
if isinstance(codec, TypeDecoder):
|
165
|
+
is_valid_codec = True
|
166
|
+
self._decoder_map[codec.bson_type] = codec.transform_bson
|
167
|
+
if not is_valid_codec:
|
168
|
+
raise TypeError(
|
169
|
+
"Expected an instance of %s, %s, or %s, got %r instead"
|
170
|
+
% (TypeEncoder.__name__, TypeDecoder.__name__, TypeCodec.__name__, codec)
|
171
|
+
)
|
172
|
+
|
173
|
+
def _validate_type_encoder(self, codec: _Codec) -> None:
|
174
|
+
from bson import _BUILT_IN_TYPES
|
175
|
+
|
176
|
+
for pytype in _BUILT_IN_TYPES:
|
177
|
+
if issubclass(cast(TypeCodec, codec).python_type, pytype):
|
178
|
+
err_msg = (
|
179
|
+
"TypeEncoders cannot change how built-in types are "
|
180
|
+
"encoded (encoder %s transforms type %s)" % (codec, pytype)
|
181
|
+
)
|
182
|
+
raise TypeError(err_msg)
|
183
|
+
|
184
|
+
def __repr__(self):
|
185
|
+
return "%s(type_codecs=%r, fallback_encoder=%r)" % (
|
186
|
+
self.__class__.__name__,
|
187
|
+
self.__type_codecs,
|
188
|
+
self._fallback_encoder,
|
189
|
+
)
|
190
|
+
|
191
|
+
def __eq__(self, other: Any) -> Any:
|
192
|
+
if not isinstance(other, type(self)):
|
193
|
+
return NotImplemented
|
194
|
+
return (
|
195
|
+
(self._decoder_map == other._decoder_map)
|
196
|
+
and (self._encoder_map == other._encoder_map)
|
197
|
+
and (self._fallback_encoder == other._fallback_encoder)
|
198
|
+
)
|
199
|
+
|
200
|
+
|
201
|
+
class _BaseCodecOptions(NamedTuple):
|
202
|
+
document_class: Type[Mapping[str, Any]]
|
203
|
+
tz_aware: bool
|
204
|
+
uuid_representation: int
|
205
|
+
unicode_decode_error_handler: str
|
206
|
+
tzinfo: Optional[datetime.tzinfo]
|
207
|
+
type_registry: TypeRegistry
|
208
|
+
|
209
|
+
|
210
|
+
class CodecOptions(_BaseCodecOptions):
|
211
|
+
"""Encapsulates options used encoding and / or decoding BSON.
|
212
|
+
|
213
|
+
The `document_class` option is used to define a custom type for use
|
214
|
+
decoding BSON documents. Access to the underlying raw BSON bytes for
|
215
|
+
a document is available using the :class:`~bson.raw_bson.RawBSONDocument`
|
216
|
+
type::
|
217
|
+
|
218
|
+
>>> from bson.raw_bson import RawBSONDocument
|
219
|
+
>>> from bson.codec_options import CodecOptions
|
220
|
+
>>> codec_options = CodecOptions(document_class=RawBSONDocument)
|
221
|
+
>>> coll = db.get_collection('test', codec_options=codec_options)
|
222
|
+
>>> doc = coll.find_one()
|
223
|
+
>>> doc.raw
|
224
|
+
'\\x16\\x00\\x00\\x00\\x07_id\\x00[0\\x165\\x91\\x10\\xea\\x14\\xe8\\xc5\\x8b\\x93\\x00'
|
225
|
+
|
226
|
+
The document class can be any type that inherits from
|
227
|
+
:class:`~collections.abc.MutableMapping`::
|
228
|
+
|
229
|
+
>>> class AttributeDict(dict):
|
230
|
+
... # A dict that supports attribute access.
|
231
|
+
... def __getattr__(self, key):
|
232
|
+
... return self[key]
|
233
|
+
... def __setattr__(self, key, value):
|
234
|
+
... self[key] = value
|
235
|
+
...
|
236
|
+
>>> codec_options = CodecOptions(document_class=AttributeDict)
|
237
|
+
>>> coll = db.get_collection('test', codec_options=codec_options)
|
238
|
+
>>> doc = coll.find_one()
|
239
|
+
>>> doc._id
|
240
|
+
ObjectId('5b3016359110ea14e8c58b93')
|
241
|
+
|
242
|
+
See :doc:`/examples/datetimes` for examples using the `tz_aware` and
|
243
|
+
`tzinfo` options.
|
244
|
+
|
245
|
+
See :doc:`/examples/uuid` for examples using the `uuid_representation`
|
246
|
+
option.
|
247
|
+
|
248
|
+
:Parameters:
|
249
|
+
- `document_class`: BSON documents returned in queries will be decoded
|
250
|
+
to an instance of this class. Must be a subclass of
|
251
|
+
:class:`~collections.abc.MutableMapping`. Defaults to :class:`dict`.
|
252
|
+
- `tz_aware`: If ``True``, BSON datetimes will be decoded to timezone
|
253
|
+
aware instances of :class:`~datetime.datetime`. Otherwise they will be
|
254
|
+
naive. Defaults to ``False``.
|
255
|
+
- `uuid_representation`: The BSON representation to use when encoding
|
256
|
+
and decoding instances of :class:`~uuid.UUID`. Defaults to
|
257
|
+
:data:`~bson.binary.UuidRepresentation.UNSPECIFIED`. New
|
258
|
+
applications should consider setting this to
|
259
|
+
:data:`~bson.binary.UuidRepresentation.STANDARD` for cross language
|
260
|
+
compatibility. See :ref:`handling-uuid-data-example` for details.
|
261
|
+
- `unicode_decode_error_handler`: The error handler to apply when
|
262
|
+
a Unicode-related error occurs during BSON decoding that would
|
263
|
+
otherwise raise :exc:`UnicodeDecodeError`. Valid options include
|
264
|
+
'strict', 'replace', 'backslashreplace', 'surrogateescape', and
|
265
|
+
'ignore'. Defaults to 'strict'.
|
266
|
+
- `tzinfo`: A :class:`~datetime.tzinfo` subclass that specifies the
|
267
|
+
timezone to/from which :class:`~datetime.datetime` objects should be
|
268
|
+
encoded/decoded.
|
269
|
+
- `type_registry`: Instance of :class:`TypeRegistry` used to customize
|
270
|
+
encoding and decoding behavior.
|
271
|
+
|
272
|
+
.. versionchanged:: 4.0
|
273
|
+
The default for `uuid_representation` was changed from
|
274
|
+
:const:`~bson.binary.UuidRepresentation.PYTHON_LEGACY` to
|
275
|
+
:const:`~bson.binary.UuidRepresentation.UNSPECIFIED`.
|
276
|
+
|
277
|
+
.. versionadded:: 3.8
|
278
|
+
`type_registry` attribute.
|
279
|
+
|
280
|
+
.. warning:: Care must be taken when changing
|
281
|
+
`unicode_decode_error_handler` from its default value ('strict').
|
282
|
+
The 'replace' and 'ignore' modes should not be used when documents
|
283
|
+
retrieved from the server will be modified in the client application
|
284
|
+
and stored back to the server.
|
285
|
+
"""
|
286
|
+
|
287
|
+
def __new__(
|
288
|
+
cls: Type["CodecOptions"],
|
289
|
+
document_class: Optional[Type[Mapping[str, Any]]] = None,
|
290
|
+
tz_aware: bool = False,
|
291
|
+
uuid_representation: Optional[int] = UuidRepresentation.UNSPECIFIED,
|
292
|
+
unicode_decode_error_handler: str = "strict",
|
293
|
+
tzinfo: Optional[datetime.tzinfo] = None,
|
294
|
+
type_registry: Optional[TypeRegistry] = None,
|
295
|
+
) -> "CodecOptions":
|
296
|
+
doc_class = document_class or dict
|
297
|
+
# issubclass can raise TypeError for generic aliases like SON[str, Any].
|
298
|
+
# In that case we can use the base class for the comparison.
|
299
|
+
is_mapping = False
|
300
|
+
try:
|
301
|
+
is_mapping = issubclass(doc_class, _MutableMapping)
|
302
|
+
except TypeError:
|
303
|
+
if hasattr(doc_class, "__origin__"):
|
304
|
+
is_mapping = issubclass(doc_class.__origin__, _MutableMapping) # type: ignore[union-attr]
|
305
|
+
if not (is_mapping or _raw_document_class(doc_class)):
|
306
|
+
raise TypeError(
|
307
|
+
"document_class must be dict, bson.son.SON, "
|
308
|
+
"bson.raw_bson.RawBSONDocument, or a "
|
309
|
+
"subclass of collections.abc.MutableMapping"
|
310
|
+
)
|
311
|
+
if not isinstance(tz_aware, bool):
|
312
|
+
raise TypeError("tz_aware must be True or False")
|
313
|
+
if uuid_representation not in ALL_UUID_REPRESENTATIONS:
|
314
|
+
raise ValueError(
|
315
|
+
"uuid_representation must be a value from bson.binary.UuidRepresentation"
|
316
|
+
)
|
317
|
+
if not isinstance(unicode_decode_error_handler, str):
|
318
|
+
raise ValueError("unicode_decode_error_handler must be a string")
|
319
|
+
if tzinfo is not None:
|
320
|
+
if not isinstance(tzinfo, datetime.tzinfo):
|
321
|
+
raise TypeError("tzinfo must be an instance of datetime.tzinfo")
|
322
|
+
if not tz_aware:
|
323
|
+
raise ValueError("cannot specify tzinfo without also setting tz_aware=True")
|
324
|
+
|
325
|
+
type_registry = type_registry or TypeRegistry()
|
326
|
+
|
327
|
+
if not isinstance(type_registry, TypeRegistry):
|
328
|
+
raise TypeError("type_registry must be an instance of TypeRegistry")
|
329
|
+
|
330
|
+
return tuple.__new__(
|
331
|
+
cls,
|
332
|
+
(
|
333
|
+
doc_class,
|
334
|
+
tz_aware,
|
335
|
+
uuid_representation,
|
336
|
+
unicode_decode_error_handler,
|
337
|
+
tzinfo,
|
338
|
+
type_registry,
|
339
|
+
),
|
340
|
+
)
|
341
|
+
|
342
|
+
def _arguments_repr(self) -> str:
|
343
|
+
"""Representation of the arguments used to create this object."""
|
344
|
+
document_class_repr = "dict" if self.document_class is dict else repr(self.document_class)
|
345
|
+
|
346
|
+
uuid_rep_repr = UUID_REPRESENTATION_NAMES.get(
|
347
|
+
self.uuid_representation, self.uuid_representation
|
348
|
+
)
|
349
|
+
|
350
|
+
return (
|
351
|
+
"document_class=%s, tz_aware=%r, uuid_representation=%s, "
|
352
|
+
"unicode_decode_error_handler=%r, tzinfo=%r, "
|
353
|
+
"type_registry=%r"
|
354
|
+
% (
|
355
|
+
document_class_repr,
|
356
|
+
self.tz_aware,
|
357
|
+
uuid_rep_repr,
|
358
|
+
self.unicode_decode_error_handler,
|
359
|
+
self.tzinfo,
|
360
|
+
self.type_registry,
|
361
|
+
)
|
362
|
+
)
|
363
|
+
|
364
|
+
def _options_dict(self) -> Dict[str, Any]:
|
365
|
+
"""Dictionary of the arguments used to create this object."""
|
366
|
+
# TODO: PYTHON-2442 use _asdict() instead
|
367
|
+
return {
|
368
|
+
"document_class": self.document_class,
|
369
|
+
"tz_aware": self.tz_aware,
|
370
|
+
"uuid_representation": self.uuid_representation,
|
371
|
+
"unicode_decode_error_handler": self.unicode_decode_error_handler,
|
372
|
+
"tzinfo": self.tzinfo,
|
373
|
+
"type_registry": self.type_registry,
|
374
|
+
}
|
375
|
+
|
376
|
+
def __repr__(self):
|
377
|
+
return "%s(%s)" % (self.__class__.__name__, self._arguments_repr())
|
378
|
+
|
379
|
+
def with_options(self, **kwargs: Any) -> "CodecOptions":
|
380
|
+
"""Make a copy of this CodecOptions, overriding some options::
|
381
|
+
|
382
|
+
>>> from bson.codec_options import DEFAULT_CODEC_OPTIONS
|
383
|
+
>>> DEFAULT_CODEC_OPTIONS.tz_aware
|
384
|
+
False
|
385
|
+
>>> options = DEFAULT_CODEC_OPTIONS.with_options(tz_aware=True)
|
386
|
+
>>> options.tz_aware
|
387
|
+
True
|
388
|
+
|
389
|
+
.. versionadded:: 3.5
|
390
|
+
"""
|
391
|
+
opts = self._options_dict()
|
392
|
+
opts.update(kwargs)
|
393
|
+
return CodecOptions(**opts)
|
394
|
+
|
395
|
+
|
396
|
+
DEFAULT_CODEC_OPTIONS = CodecOptions()
|
397
|
+
|
398
|
+
|
399
|
+
def _parse_codec_options(options: Any) -> CodecOptions:
|
400
|
+
"""Parse BSON codec options."""
|
401
|
+
kwargs = {}
|
402
|
+
for k in set(options) & {
|
403
|
+
"document_class",
|
404
|
+
"tz_aware",
|
405
|
+
"uuidrepresentation",
|
406
|
+
"unicode_decode_error_handler",
|
407
|
+
"tzinfo",
|
408
|
+
"type_registry",
|
409
|
+
}:
|
410
|
+
if k == "uuidrepresentation":
|
411
|
+
kwargs["uuid_representation"] = options[k]
|
412
|
+
else:
|
413
|
+
kwargs[k] = options[k]
|
414
|
+
return CodecOptions(**kwargs)
|
@@ -0,0 +1,100 @@
|
|
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
|
+
"""Workaround for https://bugs.python.org/issue43923.
|
16
|
+
Ideally we would have done this with a single class, but
|
17
|
+
generic subclasses *must* take a parameter, and prior to Python 3.9
|
18
|
+
or in Python 3.7 and 3.8 with `from __future__ import annotations`,
|
19
|
+
you get the error: "TypeError: 'type' object is not subscriptable".
|
20
|
+
"""
|
21
|
+
|
22
|
+
import datetime
|
23
|
+
import abc
|
24
|
+
from typing import Tuple, Generic, Optional, Mapping, Any, TypeVar, Type, Dict, Iterable, Tuple, MutableMapping, Callable, Union
|
25
|
+
|
26
|
+
|
27
|
+
class TypeEncoder(abc.ABC, metaclass=abc.ABCMeta):
|
28
|
+
@property
|
29
|
+
@abc.abstractmethod
|
30
|
+
def python_type(self) -> Any: ...
|
31
|
+
@abc.abstractmethod
|
32
|
+
def transform_python(self, value: Any) -> Any: ...
|
33
|
+
|
34
|
+
class TypeDecoder(abc.ABC, metaclass=abc.ABCMeta):
|
35
|
+
@property
|
36
|
+
@abc.abstractmethod
|
37
|
+
def bson_type(self) -> Any: ...
|
38
|
+
@abc.abstractmethod
|
39
|
+
def transform_bson(self, value: Any) -> Any: ...
|
40
|
+
|
41
|
+
class TypeCodec(TypeEncoder, TypeDecoder, metaclass=abc.ABCMeta): ...
|
42
|
+
|
43
|
+
Codec = Union[TypeEncoder, TypeDecoder, TypeCodec]
|
44
|
+
Fallback = Callable[[Any], Any]
|
45
|
+
|
46
|
+
class TypeRegistry:
|
47
|
+
_decoder_map: Dict[Any, Any]
|
48
|
+
_encoder_map: Dict[Any, Any]
|
49
|
+
_fallback_encoder: Optional[Fallback]
|
50
|
+
|
51
|
+
def __init__(self, type_codecs: Optional[Iterable[Codec]] = ..., fallback_encoder: Optional[Fallback] = ...) -> None: ...
|
52
|
+
def __eq__(self, other: Any) -> Any: ...
|
53
|
+
|
54
|
+
|
55
|
+
_DocumentType = TypeVar("_DocumentType", bound=Mapping[str, Any])
|
56
|
+
|
57
|
+
|
58
|
+
class CodecOptions(Tuple, Generic[_DocumentType]):
|
59
|
+
document_class: Type[_DocumentType]
|
60
|
+
tz_aware: bool
|
61
|
+
uuid_representation: int
|
62
|
+
unicode_decode_error_handler: Optional[str]
|
63
|
+
tzinfo: Optional[datetime.tzinfo]
|
64
|
+
type_registry: TypeRegistry
|
65
|
+
|
66
|
+
def __new__(
|
67
|
+
cls: Type[CodecOptions],
|
68
|
+
document_class: Optional[Type[_DocumentType]] = ...,
|
69
|
+
tz_aware: bool = ...,
|
70
|
+
uuid_representation: Optional[int] = ...,
|
71
|
+
unicode_decode_error_handler: Optional[str] = ...,
|
72
|
+
tzinfo: Optional[datetime.tzinfo] = ...,
|
73
|
+
type_registry: Optional[TypeRegistry] = ...,
|
74
|
+
) -> CodecOptions[_DocumentType]: ...
|
75
|
+
|
76
|
+
# CodecOptions API
|
77
|
+
def with_options(self, **kwargs: Any) -> CodecOptions[_DocumentType]: ...
|
78
|
+
|
79
|
+
def _arguments_repr(self) -> str: ...
|
80
|
+
|
81
|
+
def _options_dict(self) -> Dict[Any, Any]: ...
|
82
|
+
|
83
|
+
# NamedTuple API
|
84
|
+
@classmethod
|
85
|
+
def _make(cls, obj: Iterable) -> CodecOptions[_DocumentType]: ...
|
86
|
+
|
87
|
+
def _asdict(self) -> Dict[str, Any]: ...
|
88
|
+
|
89
|
+
def _replace(self, **kwargs: Any) -> CodecOptions[_DocumentType]: ...
|
90
|
+
|
91
|
+
_source: str
|
92
|
+
_fields: Tuple[str]
|
93
|
+
|
94
|
+
|
95
|
+
DEFAULT_CODEC_OPTIONS: CodecOptions[MutableMapping[str, Any]]
|
96
|
+
_RAW_BSON_DOCUMENT_MARKER: int
|
97
|
+
|
98
|
+
def _raw_document_class(document_class: Any) -> bool: ...
|
99
|
+
|
100
|
+
def _parse_codec_options(options: Any) -> CodecOptions: ...
|
data/lib/bson/dbref.py
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Copyright 2009-2015 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
|
+
"""Tools for manipulating DBRefs (references to MongoDB documents)."""
|
16
|
+
|
17
|
+
from copy import deepcopy
|
18
|
+
from typing import Any, Mapping, Optional
|
19
|
+
|
20
|
+
from bson._helpers import _getstate_slots, _setstate_slots
|
21
|
+
from bson.son import SON
|
22
|
+
|
23
|
+
|
24
|
+
class DBRef(object):
|
25
|
+
"""A reference to a document stored in MongoDB."""
|
26
|
+
|
27
|
+
__slots__ = "__collection", "__id", "__database", "__kwargs"
|
28
|
+
__getstate__ = _getstate_slots
|
29
|
+
__setstate__ = _setstate_slots
|
30
|
+
# DBRef isn't actually a BSON "type" so this number was arbitrarily chosen.
|
31
|
+
_type_marker = 100
|
32
|
+
|
33
|
+
def __init__(
|
34
|
+
self,
|
35
|
+
collection: str,
|
36
|
+
id: Any,
|
37
|
+
database: Optional[str] = None,
|
38
|
+
_extra: Optional[Mapping[str, Any]] = None,
|
39
|
+
**kwargs: Any
|
40
|
+
) -> None:
|
41
|
+
"""Initialize a new :class:`DBRef`.
|
42
|
+
|
43
|
+
Raises :class:`TypeError` if `collection` or `database` is not
|
44
|
+
an instance of :class:`basestring` (:class:`str` in python 3).
|
45
|
+
`database` is optional and allows references to documents to work
|
46
|
+
across databases. Any additional keyword arguments will create
|
47
|
+
additional fields in the resultant embedded document.
|
48
|
+
|
49
|
+
:Parameters:
|
50
|
+
- `collection`: name of the collection the document is stored in
|
51
|
+
- `id`: the value of the document's ``"_id"`` field
|
52
|
+
- `database` (optional): name of the database to reference
|
53
|
+
- `**kwargs` (optional): additional keyword arguments will
|
54
|
+
create additional, custom fields
|
55
|
+
|
56
|
+
.. seealso:: The MongoDB documentation on `dbrefs <https://dochub.mongodb.org/core/dbrefs>`_.
|
57
|
+
"""
|
58
|
+
if not isinstance(collection, str):
|
59
|
+
raise TypeError("collection must be an instance of str")
|
60
|
+
if database is not None and not isinstance(database, str):
|
61
|
+
raise TypeError("database must be an instance of str")
|
62
|
+
|
63
|
+
self.__collection = collection
|
64
|
+
self.__id = id
|
65
|
+
self.__database = database
|
66
|
+
kwargs.update(_extra or {})
|
67
|
+
self.__kwargs = kwargs
|
68
|
+
|
69
|
+
@property
|
70
|
+
def collection(self) -> str:
|
71
|
+
"""Get the name of this DBRef's collection."""
|
72
|
+
return self.__collection
|
73
|
+
|
74
|
+
@property
|
75
|
+
def id(self) -> Any:
|
76
|
+
"""Get this DBRef's _id."""
|
77
|
+
return self.__id
|
78
|
+
|
79
|
+
@property
|
80
|
+
def database(self) -> Optional[str]:
|
81
|
+
"""Get the name of this DBRef's database.
|
82
|
+
|
83
|
+
Returns None if this DBRef doesn't specify a database.
|
84
|
+
"""
|
85
|
+
return self.__database
|
86
|
+
|
87
|
+
def __getattr__(self, key: Any) -> Any:
|
88
|
+
try:
|
89
|
+
return self.__kwargs[key]
|
90
|
+
except KeyError:
|
91
|
+
raise AttributeError(key)
|
92
|
+
|
93
|
+
def as_doc(self) -> SON[str, Any]:
|
94
|
+
"""Get the SON document representation of this DBRef.
|
95
|
+
|
96
|
+
Generally not needed by application developers
|
97
|
+
"""
|
98
|
+
doc = SON([("$ref", self.collection), ("$id", self.id)])
|
99
|
+
if self.database is not None:
|
100
|
+
doc["$db"] = self.database
|
101
|
+
doc.update(self.__kwargs)
|
102
|
+
return doc
|
103
|
+
|
104
|
+
def __repr__(self):
|
105
|
+
extra = "".join([", %s=%r" % (k, v) for k, v in self.__kwargs.items()])
|
106
|
+
if self.database is None:
|
107
|
+
return "DBRef(%r, %r%s)" % (self.collection, self.id, extra)
|
108
|
+
return "DBRef(%r, %r, %r%s)" % (self.collection, self.id, self.database, extra)
|
109
|
+
|
110
|
+
def __eq__(self, other: Any) -> bool:
|
111
|
+
if isinstance(other, DBRef):
|
112
|
+
us = (self.__database, self.__collection, self.__id, self.__kwargs)
|
113
|
+
them = (other.__database, other.__collection, other.__id, other.__kwargs)
|
114
|
+
return us == them
|
115
|
+
return NotImplemented
|
116
|
+
|
117
|
+
def __ne__(self, other: Any) -> bool:
|
118
|
+
return not self == other
|
119
|
+
|
120
|
+
def __hash__(self) -> int:
|
121
|
+
"""Get a hash value for this :class:`DBRef`."""
|
122
|
+
return hash(
|
123
|
+
(self.__collection, self.__id, self.__database, tuple(sorted(self.__kwargs.items())))
|
124
|
+
)
|
125
|
+
|
126
|
+
def __deepcopy__(self, memo: Any) -> "DBRef":
|
127
|
+
"""Support function for `copy.deepcopy()`."""
|
128
|
+
return DBRef(
|
129
|
+
deepcopy(self.__collection, memo),
|
130
|
+
deepcopy(self.__id, memo),
|
131
|
+
deepcopy(self.__database, memo),
|
132
|
+
deepcopy(self.__kwargs, memo),
|
133
|
+
)
|