sensu-plugins-mongodb-mrtrotl 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (181) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1 -0
  3. data/LICENSE +22 -0
  4. data/README.md +27 -0
  5. data/bin/check-mongodb-metric.rb +144 -0
  6. data/bin/check-mongodb-query-count.rb +267 -0
  7. data/bin/check-mongodb.py +1644 -0
  8. data/bin/check-mongodb.rb +5 -0
  9. data/bin/metrics-mongodb-replication.rb +254 -0
  10. data/bin/metrics-mongodb.rb +133 -0
  11. data/lib/bson/__init__.py +1347 -0
  12. data/lib/bson/__pycache__/__init__.cpython-310.pyc +0 -0
  13. data/lib/bson/__pycache__/_helpers.cpython-310.pyc +0 -0
  14. data/lib/bson/__pycache__/binary.cpython-310.pyc +0 -0
  15. data/lib/bson/__pycache__/code.cpython-310.pyc +0 -0
  16. data/lib/bson/__pycache__/codec_options.cpython-310.pyc +0 -0
  17. data/lib/bson/__pycache__/dbref.cpython-310.pyc +0 -0
  18. data/lib/bson/__pycache__/decimal128.cpython-310.pyc +0 -0
  19. data/lib/bson/__pycache__/errors.cpython-310.pyc +0 -0
  20. data/lib/bson/__pycache__/int64.cpython-310.pyc +0 -0
  21. data/lib/bson/__pycache__/json_util.cpython-310.pyc +0 -0
  22. data/lib/bson/__pycache__/max_key.cpython-310.pyc +0 -0
  23. data/lib/bson/__pycache__/min_key.cpython-310.pyc +0 -0
  24. data/lib/bson/__pycache__/objectid.cpython-310.pyc +0 -0
  25. data/lib/bson/__pycache__/raw_bson.cpython-310.pyc +0 -0
  26. data/lib/bson/__pycache__/regex.cpython-310.pyc +0 -0
  27. data/lib/bson/__pycache__/son.cpython-310.pyc +0 -0
  28. data/lib/bson/__pycache__/timestamp.cpython-310.pyc +0 -0
  29. data/lib/bson/__pycache__/tz_util.cpython-310.pyc +0 -0
  30. data/lib/bson/_cbson.cpython-310-x86_64-linux-gnu.so +0 -0
  31. data/lib/bson/_helpers.py +41 -0
  32. data/lib/bson/binary.py +364 -0
  33. data/lib/bson/code.py +101 -0
  34. data/lib/bson/codec_options.py +414 -0
  35. data/lib/bson/codec_options.pyi +100 -0
  36. data/lib/bson/dbref.py +133 -0
  37. data/lib/bson/decimal128.py +314 -0
  38. data/lib/bson/errors.py +35 -0
  39. data/lib/bson/int64.py +39 -0
  40. data/lib/bson/json_util.py +874 -0
  41. data/lib/bson/max_key.py +55 -0
  42. data/lib/bson/min_key.py +55 -0
  43. data/lib/bson/objectid.py +286 -0
  44. data/lib/bson/py.typed +2 -0
  45. data/lib/bson/raw_bson.py +175 -0
  46. data/lib/bson/regex.py +135 -0
  47. data/lib/bson/son.py +208 -0
  48. data/lib/bson/timestamp.py +124 -0
  49. data/lib/bson/tz_util.py +52 -0
  50. data/lib/gridfs/__init__.py +1015 -0
  51. data/lib/gridfs/__pycache__/__init__.cpython-310.pyc +0 -0
  52. data/lib/gridfs/__pycache__/errors.cpython-310.pyc +0 -0
  53. data/lib/gridfs/__pycache__/grid_file.cpython-310.pyc +0 -0
  54. data/lib/gridfs/errors.py +33 -0
  55. data/lib/gridfs/grid_file.py +907 -0
  56. data/lib/gridfs/py.typed +2 -0
  57. data/lib/pymongo/__init__.py +185 -0
  58. data/lib/pymongo/__pycache__/__init__.cpython-310.pyc +0 -0
  59. data/lib/pymongo/__pycache__/_csot.cpython-310.pyc +0 -0
  60. data/lib/pymongo/__pycache__/aggregation.cpython-310.pyc +0 -0
  61. data/lib/pymongo/__pycache__/auth.cpython-310.pyc +0 -0
  62. data/lib/pymongo/__pycache__/auth_aws.cpython-310.pyc +0 -0
  63. data/lib/pymongo/__pycache__/bulk.cpython-310.pyc +0 -0
  64. data/lib/pymongo/__pycache__/change_stream.cpython-310.pyc +0 -0
  65. data/lib/pymongo/__pycache__/client_options.cpython-310.pyc +0 -0
  66. data/lib/pymongo/__pycache__/client_session.cpython-310.pyc +0 -0
  67. data/lib/pymongo/__pycache__/collation.cpython-310.pyc +0 -0
  68. data/lib/pymongo/__pycache__/collection.cpython-310.pyc +0 -0
  69. data/lib/pymongo/__pycache__/command_cursor.cpython-310.pyc +0 -0
  70. data/lib/pymongo/__pycache__/common.cpython-310.pyc +0 -0
  71. data/lib/pymongo/__pycache__/compression_support.cpython-310.pyc +0 -0
  72. data/lib/pymongo/__pycache__/cursor.cpython-310.pyc +0 -0
  73. data/lib/pymongo/__pycache__/daemon.cpython-310.pyc +0 -0
  74. data/lib/pymongo/__pycache__/database.cpython-310.pyc +0 -0
  75. data/lib/pymongo/__pycache__/driver_info.cpython-310.pyc +0 -0
  76. data/lib/pymongo/__pycache__/encryption.cpython-310.pyc +0 -0
  77. data/lib/pymongo/__pycache__/encryption_options.cpython-310.pyc +0 -0
  78. data/lib/pymongo/__pycache__/errors.cpython-310.pyc +0 -0
  79. data/lib/pymongo/__pycache__/event_loggers.cpython-310.pyc +0 -0
  80. data/lib/pymongo/__pycache__/hello.cpython-310.pyc +0 -0
  81. data/lib/pymongo/__pycache__/helpers.cpython-310.pyc +0 -0
  82. data/lib/pymongo/__pycache__/max_staleness_selectors.cpython-310.pyc +0 -0
  83. data/lib/pymongo/__pycache__/message.cpython-310.pyc +0 -0
  84. data/lib/pymongo/__pycache__/mongo_client.cpython-310.pyc +0 -0
  85. data/lib/pymongo/__pycache__/monitor.cpython-310.pyc +0 -0
  86. data/lib/pymongo/__pycache__/monitoring.cpython-310.pyc +0 -0
  87. data/lib/pymongo/__pycache__/network.cpython-310.pyc +0 -0
  88. data/lib/pymongo/__pycache__/ocsp_cache.cpython-310.pyc +0 -0
  89. data/lib/pymongo/__pycache__/ocsp_support.cpython-310.pyc +0 -0
  90. data/lib/pymongo/__pycache__/operations.cpython-310.pyc +0 -0
  91. data/lib/pymongo/__pycache__/periodic_executor.cpython-310.pyc +0 -0
  92. data/lib/pymongo/__pycache__/pool.cpython-310.pyc +0 -0
  93. data/lib/pymongo/__pycache__/pyopenssl_context.cpython-310.pyc +0 -0
  94. data/lib/pymongo/__pycache__/read_concern.cpython-310.pyc +0 -0
  95. data/lib/pymongo/__pycache__/read_preferences.cpython-310.pyc +0 -0
  96. data/lib/pymongo/__pycache__/response.cpython-310.pyc +0 -0
  97. data/lib/pymongo/__pycache__/results.cpython-310.pyc +0 -0
  98. data/lib/pymongo/__pycache__/saslprep.cpython-310.pyc +0 -0
  99. data/lib/pymongo/__pycache__/server.cpython-310.pyc +0 -0
  100. data/lib/pymongo/__pycache__/server_api.cpython-310.pyc +0 -0
  101. data/lib/pymongo/__pycache__/server_description.cpython-310.pyc +0 -0
  102. data/lib/pymongo/__pycache__/server_selectors.cpython-310.pyc +0 -0
  103. data/lib/pymongo/__pycache__/server_type.cpython-310.pyc +0 -0
  104. data/lib/pymongo/__pycache__/settings.cpython-310.pyc +0 -0
  105. data/lib/pymongo/__pycache__/socket_checker.cpython-310.pyc +0 -0
  106. data/lib/pymongo/__pycache__/srv_resolver.cpython-310.pyc +0 -0
  107. data/lib/pymongo/__pycache__/ssl_context.cpython-310.pyc +0 -0
  108. data/lib/pymongo/__pycache__/ssl_support.cpython-310.pyc +0 -0
  109. data/lib/pymongo/__pycache__/topology.cpython-310.pyc +0 -0
  110. data/lib/pymongo/__pycache__/topology_description.cpython-310.pyc +0 -0
  111. data/lib/pymongo/__pycache__/typings.cpython-310.pyc +0 -0
  112. data/lib/pymongo/__pycache__/uri_parser.cpython-310.pyc +0 -0
  113. data/lib/pymongo/__pycache__/write_concern.cpython-310.pyc +0 -0
  114. data/lib/pymongo/_cmessage.cpython-310-x86_64-linux-gnu.so +0 -0
  115. data/lib/pymongo/_csot.py +118 -0
  116. data/lib/pymongo/aggregation.py +229 -0
  117. data/lib/pymongo/auth.py +549 -0
  118. data/lib/pymongo/auth_aws.py +94 -0
  119. data/lib/pymongo/bulk.py +513 -0
  120. data/lib/pymongo/change_stream.py +457 -0
  121. data/lib/pymongo/client_options.py +302 -0
  122. data/lib/pymongo/client_session.py +1112 -0
  123. data/lib/pymongo/collation.py +224 -0
  124. data/lib/pymongo/collection.py +3204 -0
  125. data/lib/pymongo/command_cursor.py +353 -0
  126. data/lib/pymongo/common.py +984 -0
  127. data/lib/pymongo/compression_support.py +149 -0
  128. data/lib/pymongo/cursor.py +1345 -0
  129. data/lib/pymongo/daemon.py +141 -0
  130. data/lib/pymongo/database.py +1202 -0
  131. data/lib/pymongo/driver_info.py +42 -0
  132. data/lib/pymongo/encryption.py +884 -0
  133. data/lib/pymongo/encryption_options.py +221 -0
  134. data/lib/pymongo/errors.py +365 -0
  135. data/lib/pymongo/event_loggers.py +221 -0
  136. data/lib/pymongo/hello.py +219 -0
  137. data/lib/pymongo/helpers.py +259 -0
  138. data/lib/pymongo/max_staleness_selectors.py +114 -0
  139. data/lib/pymongo/message.py +1440 -0
  140. data/lib/pymongo/mongo_client.py +2144 -0
  141. data/lib/pymongo/monitor.py +440 -0
  142. data/lib/pymongo/monitoring.py +1801 -0
  143. data/lib/pymongo/network.py +311 -0
  144. data/lib/pymongo/ocsp_cache.py +87 -0
  145. data/lib/pymongo/ocsp_support.py +372 -0
  146. data/lib/pymongo/operations.py +507 -0
  147. data/lib/pymongo/periodic_executor.py +183 -0
  148. data/lib/pymongo/pool.py +1660 -0
  149. data/lib/pymongo/py.typed +2 -0
  150. data/lib/pymongo/pyopenssl_context.py +383 -0
  151. data/lib/pymongo/read_concern.py +75 -0
  152. data/lib/pymongo/read_preferences.py +609 -0
  153. data/lib/pymongo/response.py +109 -0
  154. data/lib/pymongo/results.py +217 -0
  155. data/lib/pymongo/saslprep.py +113 -0
  156. data/lib/pymongo/server.py +247 -0
  157. data/lib/pymongo/server_api.py +170 -0
  158. data/lib/pymongo/server_description.py +285 -0
  159. data/lib/pymongo/server_selectors.py +153 -0
  160. data/lib/pymongo/server_type.py +32 -0
  161. data/lib/pymongo/settings.py +159 -0
  162. data/lib/pymongo/socket_checker.py +104 -0
  163. data/lib/pymongo/srv_resolver.py +126 -0
  164. data/lib/pymongo/ssl_context.py +39 -0
  165. data/lib/pymongo/ssl_support.py +99 -0
  166. data/lib/pymongo/topology.py +890 -0
  167. data/lib/pymongo/topology_description.py +639 -0
  168. data/lib/pymongo/typings.py +39 -0
  169. data/lib/pymongo/uri_parser.py +624 -0
  170. data/lib/pymongo/write_concern.py +129 -0
  171. data/lib/pymongo-4.2.0.dist-info/INSTALLER +1 -0
  172. data/lib/pymongo-4.2.0.dist-info/LICENSE +201 -0
  173. data/lib/pymongo-4.2.0.dist-info/METADATA +250 -0
  174. data/lib/pymongo-4.2.0.dist-info/RECORD +167 -0
  175. data/lib/pymongo-4.2.0.dist-info/REQUESTED +0 -0
  176. data/lib/pymongo-4.2.0.dist-info/WHEEL +6 -0
  177. data/lib/pymongo-4.2.0.dist-info/top_level.txt +3 -0
  178. data/lib/sensu-plugins-mongodb/metrics.rb +391 -0
  179. data/lib/sensu-plugins-mongodb/version.rb +9 -0
  180. data/lib/sensu-plugins-mongodb.rb +1 -0
  181. metadata +407 -0
@@ -0,0 +1,1015 @@
1
+ # Copyright 2009-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
+ """GridFS is a specification for storing large objects in Mongo.
16
+
17
+ The :mod:`gridfs` package is an implementation of GridFS on top of
18
+ :mod:`pymongo`, exposing a file-like interface.
19
+
20
+ .. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
21
+ """
22
+
23
+ from collections import abc
24
+ from typing import Any, List, Mapping, Optional, cast
25
+
26
+ from bson.objectid import ObjectId
27
+ from gridfs.errors import NoFile
28
+ from gridfs.grid_file import (
29
+ DEFAULT_CHUNK_SIZE,
30
+ GridIn,
31
+ GridOut,
32
+ GridOutCursor,
33
+ _clear_entity_type_registry,
34
+ _disallow_transactions,
35
+ )
36
+ from pymongo import ASCENDING, DESCENDING, _csot
37
+ from pymongo.client_session import ClientSession
38
+ from pymongo.collection import Collection
39
+ from pymongo.common import validate_string
40
+ from pymongo.database import Database
41
+ from pymongo.errors import ConfigurationError
42
+ from pymongo.read_preferences import _ServerMode
43
+ from pymongo.write_concern import WriteConcern
44
+
45
+ __all__ = [
46
+ "GridFS",
47
+ "GridFSBucket",
48
+ "NoFile",
49
+ "DEFAULT_CHUNK_SIZE",
50
+ "GridIn",
51
+ "GridOut",
52
+ "GridOutCursor",
53
+ ]
54
+
55
+
56
+ class GridFS(object):
57
+ """An instance of GridFS on top of a single Database."""
58
+
59
+ def __init__(self, database: Database, collection: str = "fs"):
60
+ """Create a new instance of :class:`GridFS`.
61
+
62
+ Raises :class:`TypeError` if `database` is not an instance of
63
+ :class:`~pymongo.database.Database`.
64
+
65
+ :Parameters:
66
+ - `database`: database to use
67
+ - `collection` (optional): root collection to use
68
+
69
+ .. versionchanged:: 4.0
70
+ Removed the `disable_md5` parameter. See
71
+ :ref:`removed-gridfs-checksum` for details.
72
+
73
+ .. versionchanged:: 3.11
74
+ Running a GridFS operation in a transaction now always raises an
75
+ error. GridFS does not support multi-document transactions.
76
+
77
+ .. versionchanged:: 3.7
78
+ Added the `disable_md5` parameter.
79
+
80
+ .. versionchanged:: 3.1
81
+ Indexes are only ensured on the first write to the DB.
82
+
83
+ .. versionchanged:: 3.0
84
+ `database` must use an acknowledged
85
+ :attr:`~pymongo.database.Database.write_concern`
86
+
87
+ .. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
88
+ """
89
+ if not isinstance(database, Database):
90
+ raise TypeError("database must be an instance of Database")
91
+
92
+ database = _clear_entity_type_registry(database)
93
+
94
+ if not database.write_concern.acknowledged:
95
+ raise ConfigurationError("database must use acknowledged write_concern")
96
+
97
+ self.__collection = database[collection]
98
+ self.__files = self.__collection.files
99
+ self.__chunks = self.__collection.chunks
100
+
101
+ def new_file(self, **kwargs: Any) -> GridIn:
102
+ """Create a new file in GridFS.
103
+
104
+ Returns a new :class:`~gridfs.grid_file.GridIn` instance to
105
+ which data can be written. Any keyword arguments will be
106
+ passed through to :meth:`~gridfs.grid_file.GridIn`.
107
+
108
+ If the ``"_id"`` of the file is manually specified, it must
109
+ not already exist in GridFS. Otherwise
110
+ :class:`~gridfs.errors.FileExists` is raised.
111
+
112
+ :Parameters:
113
+ - `**kwargs` (optional): keyword arguments for file creation
114
+ """
115
+ return GridIn(self.__collection, **kwargs)
116
+
117
+ def put(self, data: Any, **kwargs: Any) -> Any:
118
+ """Put data in GridFS as a new file.
119
+
120
+ Equivalent to doing::
121
+
122
+ with fs.new_file(**kwargs) as f:
123
+ f.write(data)
124
+
125
+ `data` can be either an instance of :class:`bytes` or a file-like
126
+ object providing a :meth:`read` method. If an `encoding` keyword
127
+ argument is passed, `data` can also be a :class:`str` instance, which
128
+ will be encoded as `encoding` before being written. Any keyword
129
+ arguments will be passed through to the created file - see
130
+ :meth:`~gridfs.grid_file.GridIn` for possible arguments. Returns the
131
+ ``"_id"`` of the created file.
132
+
133
+ If the ``"_id"`` of the file is manually specified, it must
134
+ not already exist in GridFS. Otherwise
135
+ :class:`~gridfs.errors.FileExists` is raised.
136
+
137
+ :Parameters:
138
+ - `data`: data to be written as a file.
139
+ - `**kwargs` (optional): keyword arguments for file creation
140
+
141
+ .. versionchanged:: 3.0
142
+ w=0 writes to GridFS are now prohibited.
143
+ """
144
+
145
+ with GridIn(self.__collection, **kwargs) as grid_file:
146
+ grid_file.write(data)
147
+ return grid_file._id
148
+
149
+ def get(self, file_id: Any, session: Optional[ClientSession] = None) -> GridOut:
150
+ """Get a file from GridFS by ``"_id"``.
151
+
152
+ Returns an instance of :class:`~gridfs.grid_file.GridOut`,
153
+ which provides a file-like interface for reading.
154
+
155
+ :Parameters:
156
+ - `file_id`: ``"_id"`` of the file to get
157
+ - `session` (optional): a
158
+ :class:`~pymongo.client_session.ClientSession`
159
+
160
+ .. versionchanged:: 3.6
161
+ Added ``session`` parameter.
162
+ """
163
+ gout = GridOut(self.__collection, file_id, session=session)
164
+
165
+ # Raise NoFile now, instead of on first attribute access.
166
+ gout._ensure_file()
167
+ return gout
168
+
169
+ def get_version(
170
+ self,
171
+ filename: Optional[str] = None,
172
+ version: Optional[int] = -1,
173
+ session: Optional[ClientSession] = None,
174
+ **kwargs: Any
175
+ ) -> GridOut:
176
+ """Get a file from GridFS by ``"filename"`` or metadata fields.
177
+
178
+ Returns a version of the file in GridFS whose filename matches
179
+ `filename` and whose metadata fields match the supplied keyword
180
+ arguments, as an instance of :class:`~gridfs.grid_file.GridOut`.
181
+
182
+ Version numbering is a convenience atop the GridFS API provided
183
+ by MongoDB. If more than one file matches the query (either by
184
+ `filename` alone, by metadata fields, or by a combination of
185
+ both), then version ``-1`` will be the most recently uploaded
186
+ matching file, ``-2`` the second most recently
187
+ uploaded, etc. Version ``0`` will be the first version
188
+ uploaded, ``1`` the second version, etc. So if three versions
189
+ have been uploaded, then version ``0`` is the same as version
190
+ ``-3``, version ``1`` is the same as version ``-2``, and
191
+ version ``2`` is the same as version ``-1``.
192
+
193
+ Raises :class:`~gridfs.errors.NoFile` if no such version of
194
+ that file exists.
195
+
196
+ :Parameters:
197
+ - `filename`: ``"filename"`` of the file to get, or `None`
198
+ - `version` (optional): version of the file to get (defaults
199
+ to -1, the most recent version uploaded)
200
+ - `session` (optional): a
201
+ :class:`~pymongo.client_session.ClientSession`
202
+ - `**kwargs` (optional): find files by custom metadata.
203
+
204
+ .. versionchanged:: 3.6
205
+ Added ``session`` parameter.
206
+
207
+ .. versionchanged:: 3.1
208
+ ``get_version`` no longer ensures indexes.
209
+ """
210
+ query = kwargs
211
+ if filename is not None:
212
+ query["filename"] = filename
213
+
214
+ _disallow_transactions(session)
215
+ cursor = self.__files.find(query, session=session)
216
+ if version is None:
217
+ version = -1
218
+ if version < 0:
219
+ skip = abs(version) - 1
220
+ cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING)
221
+ else:
222
+ cursor.limit(-1).skip(version).sort("uploadDate", ASCENDING)
223
+ try:
224
+ doc = next(cursor)
225
+ return GridOut(self.__collection, file_document=doc, session=session)
226
+ except StopIteration:
227
+ raise NoFile("no version %d for filename %r" % (version, filename))
228
+
229
+ def get_last_version(
230
+ self, filename: Optional[str] = None, session: Optional[ClientSession] = None, **kwargs: Any
231
+ ) -> GridOut:
232
+ """Get the most recent version of a file in GridFS by ``"filename"``
233
+ or metadata fields.
234
+
235
+ Equivalent to calling :meth:`get_version` with the default
236
+ `version` (``-1``).
237
+
238
+ :Parameters:
239
+ - `filename`: ``"filename"`` of the file to get, or `None`
240
+ - `session` (optional): a
241
+ :class:`~pymongo.client_session.ClientSession`
242
+ - `**kwargs` (optional): find files by custom metadata.
243
+
244
+ .. versionchanged:: 3.6
245
+ Added ``session`` parameter.
246
+ """
247
+ return self.get_version(filename=filename, session=session, **kwargs)
248
+
249
+ # TODO add optional safe mode for chunk removal?
250
+ def delete(self, file_id: Any, session: Optional[ClientSession] = None) -> None:
251
+ """Delete a file from GridFS by ``"_id"``.
252
+
253
+ Deletes all data belonging to the file with ``"_id"``:
254
+ `file_id`.
255
+
256
+ .. warning:: Any processes/threads reading from the file while
257
+ this method is executing will likely see an invalid/corrupt
258
+ file. Care should be taken to avoid concurrent reads to a file
259
+ while it is being deleted.
260
+
261
+ .. note:: Deletes of non-existent files are considered successful
262
+ since the end result is the same: no file with that _id remains.
263
+
264
+ :Parameters:
265
+ - `file_id`: ``"_id"`` of the file to delete
266
+ - `session` (optional): a
267
+ :class:`~pymongo.client_session.ClientSession`
268
+
269
+ .. versionchanged:: 3.6
270
+ Added ``session`` parameter.
271
+
272
+ .. versionchanged:: 3.1
273
+ ``delete`` no longer ensures indexes.
274
+ """
275
+ _disallow_transactions(session)
276
+ self.__files.delete_one({"_id": file_id}, session=session)
277
+ self.__chunks.delete_many({"files_id": file_id}, session=session)
278
+
279
+ def list(self, session: Optional[ClientSession] = None) -> List[str]:
280
+ """List the names of all files stored in this instance of
281
+ :class:`GridFS`.
282
+
283
+ :Parameters:
284
+ - `session` (optional): a
285
+ :class:`~pymongo.client_session.ClientSession`
286
+
287
+ .. versionchanged:: 3.6
288
+ Added ``session`` parameter.
289
+
290
+ .. versionchanged:: 3.1
291
+ ``list`` no longer ensures indexes.
292
+ """
293
+ _disallow_transactions(session)
294
+ # With an index, distinct includes documents with no filename
295
+ # as None.
296
+ return [
297
+ name for name in self.__files.distinct("filename", session=session) if name is not None
298
+ ]
299
+
300
+ def find_one(
301
+ self,
302
+ filter: Optional[Any] = None,
303
+ session: Optional[ClientSession] = None,
304
+ *args: Any,
305
+ **kwargs: Any
306
+ ) -> Optional[GridOut]:
307
+ """Get a single file from gridfs.
308
+
309
+ All arguments to :meth:`find` are also valid arguments for
310
+ :meth:`find_one`, although any `limit` argument will be
311
+ ignored. Returns a single :class:`~gridfs.grid_file.GridOut`,
312
+ or ``None`` if no matching file is found. For example::
313
+
314
+ file = fs.find_one({"filename": "lisa.txt"})
315
+
316
+ :Parameters:
317
+ - `filter` (optional): a dictionary specifying
318
+ the query to be performing OR any other type to be used as
319
+ the value for a query for ``"_id"`` in the file collection.
320
+ - `*args` (optional): any additional positional arguments are
321
+ the same as the arguments to :meth:`find`.
322
+ - `session` (optional): a
323
+ :class:`~pymongo.client_session.ClientSession`
324
+ - `**kwargs` (optional): any additional keyword arguments
325
+ are the same as the arguments to :meth:`find`.
326
+
327
+ .. versionchanged:: 3.6
328
+ Added ``session`` parameter.
329
+ """
330
+ if filter is not None and not isinstance(filter, abc.Mapping):
331
+ filter = {"_id": filter}
332
+
333
+ _disallow_transactions(session)
334
+ for f in self.find(filter, *args, session=session, **kwargs):
335
+ return f
336
+
337
+ return None
338
+
339
+ def find(self, *args: Any, **kwargs: Any) -> GridOutCursor:
340
+ """Query GridFS for files.
341
+
342
+ Returns a cursor that iterates across files matching
343
+ arbitrary queries on the files collection. Can be combined
344
+ with other modifiers for additional control. For example::
345
+
346
+ for grid_out in fs.find({"filename": "lisa.txt"},
347
+ no_cursor_timeout=True):
348
+ data = grid_out.read()
349
+
350
+ would iterate through all versions of "lisa.txt" stored in GridFS.
351
+ Note that setting no_cursor_timeout to True may be important to
352
+ prevent the cursor from timing out during long multi-file processing
353
+ work.
354
+
355
+ As another example, the call::
356
+
357
+ most_recent_three = fs.find().sort("uploadDate", -1).limit(3)
358
+
359
+ would return a cursor to the three most recently uploaded files
360
+ in GridFS.
361
+
362
+ Follows a similar interface to
363
+ :meth:`~pymongo.collection.Collection.find`
364
+ in :class:`~pymongo.collection.Collection`.
365
+
366
+ If a :class:`~pymongo.client_session.ClientSession` is passed to
367
+ :meth:`find`, all returned :class:`~gridfs.grid_file.GridOut` instances
368
+ are associated with that session.
369
+
370
+ :Parameters:
371
+ - `filter` (optional): A query document that selects which files
372
+ to include in the result set. Can be an empty document to include
373
+ all files.
374
+ - `skip` (optional): the number of files to omit (from
375
+ the start of the result set) when returning the results
376
+ - `limit` (optional): the maximum number of results to
377
+ return
378
+ - `no_cursor_timeout` (optional): if False (the default), any
379
+ returned cursor is closed by the server after 10 minutes of
380
+ inactivity. If set to True, the returned cursor will never
381
+ time out on the server. Care should be taken to ensure that
382
+ cursors with no_cursor_timeout turned on are properly closed.
383
+ - `sort` (optional): a list of (key, direction) pairs
384
+ specifying the sort order for this query. See
385
+ :meth:`~pymongo.cursor.Cursor.sort` for details.
386
+
387
+ Raises :class:`TypeError` if any of the arguments are of
388
+ improper type. Returns an instance of
389
+ :class:`~gridfs.grid_file.GridOutCursor`
390
+ corresponding to this query.
391
+
392
+ .. versionchanged:: 3.0
393
+ Removed the read_preference, tag_sets, and
394
+ secondary_acceptable_latency_ms options.
395
+ .. versionadded:: 2.7
396
+ .. seealso:: The MongoDB documentation on `find <https://dochub.mongodb.org/core/find>`_.
397
+ """
398
+ return GridOutCursor(self.__collection, *args, **kwargs)
399
+
400
+ def exists(
401
+ self,
402
+ document_or_id: Optional[Any] = None,
403
+ session: Optional[ClientSession] = None,
404
+ **kwargs: Any
405
+ ) -> bool:
406
+ """Check if a file exists in this instance of :class:`GridFS`.
407
+
408
+ The file to check for can be specified by the value of its
409
+ ``_id`` key, or by passing in a query document. A query
410
+ document can be passed in as dictionary, or by using keyword
411
+ arguments. Thus, the following three calls are equivalent:
412
+
413
+ >>> fs.exists(file_id)
414
+ >>> fs.exists({"_id": file_id})
415
+ >>> fs.exists(_id=file_id)
416
+
417
+ As are the following two calls:
418
+
419
+ >>> fs.exists({"filename": "mike.txt"})
420
+ >>> fs.exists(filename="mike.txt")
421
+
422
+ And the following two:
423
+
424
+ >>> fs.exists({"foo": {"$gt": 12}})
425
+ >>> fs.exists(foo={"$gt": 12})
426
+
427
+ Returns ``True`` if a matching file exists, ``False``
428
+ otherwise. Calls to :meth:`exists` will not automatically
429
+ create appropriate indexes; application developers should be
430
+ sure to create indexes if needed and as appropriate.
431
+
432
+ :Parameters:
433
+ - `document_or_id` (optional): query document, or _id of the
434
+ document to check for
435
+ - `session` (optional): a
436
+ :class:`~pymongo.client_session.ClientSession`
437
+ - `**kwargs` (optional): keyword arguments are used as a
438
+ query document, if they're present.
439
+
440
+ .. versionchanged:: 3.6
441
+ Added ``session`` parameter.
442
+ """
443
+ _disallow_transactions(session)
444
+ if kwargs:
445
+ f = self.__files.find_one(kwargs, ["_id"], session=session)
446
+ else:
447
+ f = self.__files.find_one(document_or_id, ["_id"], session=session)
448
+
449
+ return f is not None
450
+
451
+
452
+ class GridFSBucket(object):
453
+ """An instance of GridFS on top of a single Database."""
454
+
455
+ def __init__(
456
+ self,
457
+ db: Database,
458
+ bucket_name: str = "fs",
459
+ chunk_size_bytes: int = DEFAULT_CHUNK_SIZE,
460
+ write_concern: Optional[WriteConcern] = None,
461
+ read_preference: Optional[_ServerMode] = None,
462
+ ) -> None:
463
+ """Create a new instance of :class:`GridFSBucket`.
464
+
465
+ Raises :exc:`TypeError` if `database` is not an instance of
466
+ :class:`~pymongo.database.Database`.
467
+
468
+ Raises :exc:`~pymongo.errors.ConfigurationError` if `write_concern`
469
+ is not acknowledged.
470
+
471
+ :Parameters:
472
+ - `database`: database to use.
473
+ - `bucket_name` (optional): The name of the bucket. Defaults to 'fs'.
474
+ - `chunk_size_bytes` (optional): The chunk size in bytes. Defaults
475
+ to 255KB.
476
+ - `write_concern` (optional): The
477
+ :class:`~pymongo.write_concern.WriteConcern` to use. If ``None``
478
+ (the default) db.write_concern is used.
479
+ - `read_preference` (optional): The read preference to use. If
480
+ ``None`` (the default) db.read_preference is used.
481
+
482
+ .. versionchanged:: 4.0
483
+ Removed the `disable_md5` parameter. See
484
+ :ref:`removed-gridfs-checksum` for details.
485
+
486
+ .. versionchanged:: 3.11
487
+ Running a GridFSBucket operation in a transaction now always raises
488
+ an error. GridFSBucket does not support multi-document transactions.
489
+
490
+ .. versionchanged:: 3.7
491
+ Added the `disable_md5` parameter.
492
+
493
+ .. versionadded:: 3.1
494
+
495
+ .. seealso:: The MongoDB documentation on `gridfs <https://dochub.mongodb.org/core/gridfs>`_.
496
+ """
497
+ if not isinstance(db, Database):
498
+ raise TypeError("database must be an instance of Database")
499
+
500
+ db = _clear_entity_type_registry(db)
501
+
502
+ wtc = write_concern if write_concern is not None else db.write_concern
503
+ if not wtc.acknowledged:
504
+ raise ConfigurationError("write concern must be acknowledged")
505
+
506
+ self._bucket_name = bucket_name
507
+ self._collection = db[bucket_name]
508
+ self._chunks: Collection = self._collection.chunks.with_options(
509
+ write_concern=write_concern, read_preference=read_preference
510
+ )
511
+
512
+ self._files: Collection = self._collection.files.with_options(
513
+ write_concern=write_concern, read_preference=read_preference
514
+ )
515
+
516
+ self._chunk_size_bytes = chunk_size_bytes
517
+ self._timeout = db.client.options.timeout
518
+
519
+ def open_upload_stream(
520
+ self,
521
+ filename: str,
522
+ chunk_size_bytes: Optional[int] = None,
523
+ metadata: Optional[Mapping[str, Any]] = None,
524
+ session: Optional[ClientSession] = None,
525
+ ) -> GridIn:
526
+ """Opens a Stream that the application can write the contents of the
527
+ file to.
528
+
529
+ The user must specify the filename, and can choose to add any
530
+ additional information in the metadata field of the file document or
531
+ modify the chunk size.
532
+ For example::
533
+
534
+ my_db = MongoClient().test
535
+ fs = GridFSBucket(my_db)
536
+ with fs.open_upload_stream(
537
+ "test_file", chunk_size_bytes=4,
538
+ metadata={"contentType": "text/plain"}) as grid_in:
539
+ grid_in.write("data I want to store!")
540
+ # uploaded on close
541
+
542
+ Returns an instance of :class:`~gridfs.grid_file.GridIn`.
543
+
544
+ Raises :exc:`~gridfs.errors.NoFile` if no such version of
545
+ that file exists.
546
+ Raises :exc:`~ValueError` if `filename` is not a string.
547
+
548
+ :Parameters:
549
+ - `filename`: The name of the file to upload.
550
+ - `chunk_size_bytes` (options): The number of bytes per chunk of this
551
+ file. Defaults to the chunk_size_bytes in :class:`GridFSBucket`.
552
+ - `metadata` (optional): User data for the 'metadata' field of the
553
+ files collection document. If not provided the metadata field will
554
+ be omitted from the files collection document.
555
+ - `session` (optional): a
556
+ :class:`~pymongo.client_session.ClientSession`
557
+
558
+ .. versionchanged:: 3.6
559
+ Added ``session`` parameter.
560
+ """
561
+ validate_string("filename", filename)
562
+
563
+ opts = {
564
+ "filename": filename,
565
+ "chunk_size": (
566
+ chunk_size_bytes if chunk_size_bytes is not None else self._chunk_size_bytes
567
+ ),
568
+ }
569
+ if metadata is not None:
570
+ opts["metadata"] = metadata
571
+
572
+ return GridIn(self._collection, session=session, **opts)
573
+
574
+ def open_upload_stream_with_id(
575
+ self,
576
+ file_id: Any,
577
+ filename: str,
578
+ chunk_size_bytes: Optional[int] = None,
579
+ metadata: Optional[Mapping[str, Any]] = None,
580
+ session: Optional[ClientSession] = None,
581
+ ) -> GridIn:
582
+ """Opens a Stream that the application can write the contents of the
583
+ file to.
584
+
585
+ The user must specify the file id and filename, and can choose to add
586
+ any additional information in the metadata field of the file document
587
+ or modify the chunk size.
588
+ For example::
589
+
590
+ my_db = MongoClient().test
591
+ fs = GridFSBucket(my_db)
592
+ with fs.open_upload_stream_with_id(
593
+ ObjectId(),
594
+ "test_file",
595
+ chunk_size_bytes=4,
596
+ metadata={"contentType": "text/plain"}) as grid_in:
597
+ grid_in.write("data I want to store!")
598
+ # uploaded on close
599
+
600
+ Returns an instance of :class:`~gridfs.grid_file.GridIn`.
601
+
602
+ Raises :exc:`~gridfs.errors.NoFile` if no such version of
603
+ that file exists.
604
+ Raises :exc:`~ValueError` if `filename` is not a string.
605
+
606
+ :Parameters:
607
+ - `file_id`: The id to use for this file. The id must not have
608
+ already been used for another file.
609
+ - `filename`: The name of the file to upload.
610
+ - `chunk_size_bytes` (options): The number of bytes per chunk of this
611
+ file. Defaults to the chunk_size_bytes in :class:`GridFSBucket`.
612
+ - `metadata` (optional): User data for the 'metadata' field of the
613
+ files collection document. If not provided the metadata field will
614
+ be omitted from the files collection document.
615
+ - `session` (optional): a
616
+ :class:`~pymongo.client_session.ClientSession`
617
+
618
+ .. versionchanged:: 3.6
619
+ Added ``session`` parameter.
620
+ """
621
+ validate_string("filename", filename)
622
+
623
+ opts = {
624
+ "_id": file_id,
625
+ "filename": filename,
626
+ "chunk_size": (
627
+ chunk_size_bytes if chunk_size_bytes is not None else self._chunk_size_bytes
628
+ ),
629
+ }
630
+ if metadata is not None:
631
+ opts["metadata"] = metadata
632
+
633
+ return GridIn(self._collection, session=session, **opts)
634
+
635
+ @_csot.apply
636
+ def upload_from_stream(
637
+ self,
638
+ filename: str,
639
+ source: Any,
640
+ chunk_size_bytes: Optional[int] = None,
641
+ metadata: Optional[Mapping[str, Any]] = None,
642
+ session: Optional[ClientSession] = None,
643
+ ) -> ObjectId:
644
+ """Uploads a user file to a GridFS bucket.
645
+
646
+ Reads the contents of the user file from `source` and uploads
647
+ it to the file `filename`. Source can be a string or file-like object.
648
+ For example::
649
+
650
+ my_db = MongoClient().test
651
+ fs = GridFSBucket(my_db)
652
+ file_id = fs.upload_from_stream(
653
+ "test_file",
654
+ "data I want to store!",
655
+ chunk_size_bytes=4,
656
+ metadata={"contentType": "text/plain"})
657
+
658
+ Returns the _id of the uploaded file.
659
+
660
+ Raises :exc:`~gridfs.errors.NoFile` if no such version of
661
+ that file exists.
662
+ Raises :exc:`~ValueError` if `filename` is not a string.
663
+
664
+ :Parameters:
665
+ - `filename`: The name of the file to upload.
666
+ - `source`: The source stream of the content to be uploaded. Must be
667
+ a file-like object that implements :meth:`read` or a string.
668
+ - `chunk_size_bytes` (options): The number of bytes per chunk of this
669
+ file. Defaults to the chunk_size_bytes of :class:`GridFSBucket`.
670
+ - `metadata` (optional): User data for the 'metadata' field of the
671
+ files collection document. If not provided the metadata field will
672
+ be omitted from the files collection document.
673
+ - `session` (optional): a
674
+ :class:`~pymongo.client_session.ClientSession`
675
+
676
+ .. versionchanged:: 3.6
677
+ Added ``session`` parameter.
678
+ """
679
+ with self.open_upload_stream(filename, chunk_size_bytes, metadata, session=session) as gin:
680
+ gin.write(source)
681
+
682
+ return cast(ObjectId, gin._id)
683
+
684
+ @_csot.apply
685
+ def upload_from_stream_with_id(
686
+ self,
687
+ file_id: Any,
688
+ filename: str,
689
+ source: Any,
690
+ chunk_size_bytes: Optional[int] = None,
691
+ metadata: Optional[Mapping[str, Any]] = None,
692
+ session: Optional[ClientSession] = None,
693
+ ) -> None:
694
+ """Uploads a user file to a GridFS bucket with a custom file id.
695
+
696
+ Reads the contents of the user file from `source` and uploads
697
+ it to the file `filename`. Source can be a string or file-like object.
698
+ For example::
699
+
700
+ my_db = MongoClient().test
701
+ fs = GridFSBucket(my_db)
702
+ file_id = fs.upload_from_stream(
703
+ ObjectId(),
704
+ "test_file",
705
+ "data I want to store!",
706
+ chunk_size_bytes=4,
707
+ metadata={"contentType": "text/plain"})
708
+
709
+ Raises :exc:`~gridfs.errors.NoFile` if no such version of
710
+ that file exists.
711
+ Raises :exc:`~ValueError` if `filename` is not a string.
712
+
713
+ :Parameters:
714
+ - `file_id`: The id to use for this file. The id must not have
715
+ already been used for another file.
716
+ - `filename`: The name of the file to upload.
717
+ - `source`: The source stream of the content to be uploaded. Must be
718
+ a file-like object that implements :meth:`read` or a string.
719
+ - `chunk_size_bytes` (options): The number of bytes per chunk of this
720
+ file. Defaults to the chunk_size_bytes of :class:`GridFSBucket`.
721
+ - `metadata` (optional): User data for the 'metadata' field of the
722
+ files collection document. If not provided the metadata field will
723
+ be omitted from the files collection document.
724
+ - `session` (optional): a
725
+ :class:`~pymongo.client_session.ClientSession`
726
+
727
+ .. versionchanged:: 3.6
728
+ Added ``session`` parameter.
729
+ """
730
+ with self.open_upload_stream_with_id(
731
+ file_id, filename, chunk_size_bytes, metadata, session=session
732
+ ) as gin:
733
+ gin.write(source)
734
+
735
+ def open_download_stream(
736
+ self, file_id: Any, session: Optional[ClientSession] = None
737
+ ) -> GridOut:
738
+ """Opens a Stream from which the application can read the contents of
739
+ the stored file specified by file_id.
740
+
741
+ For example::
742
+
743
+ my_db = MongoClient().test
744
+ fs = GridFSBucket(my_db)
745
+ # get _id of file to read.
746
+ file_id = fs.upload_from_stream("test_file", "data I want to store!")
747
+ grid_out = fs.open_download_stream(file_id)
748
+ contents = grid_out.read()
749
+
750
+ Returns an instance of :class:`~gridfs.grid_file.GridOut`.
751
+
752
+ Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.
753
+
754
+ :Parameters:
755
+ - `file_id`: The _id of the file to be downloaded.
756
+ - `session` (optional): a
757
+ :class:`~pymongo.client_session.ClientSession`
758
+
759
+ .. versionchanged:: 3.6
760
+ Added ``session`` parameter.
761
+ """
762
+ gout = GridOut(self._collection, file_id, session=session)
763
+
764
+ # Raise NoFile now, instead of on first attribute access.
765
+ gout._ensure_file()
766
+ return gout
767
+
768
+ @_csot.apply
769
+ def download_to_stream(
770
+ self, file_id: Any, destination: Any, session: Optional[ClientSession] = None
771
+ ) -> None:
772
+ """Downloads the contents of the stored file specified by file_id and
773
+ writes the contents to `destination`.
774
+
775
+ For example::
776
+
777
+ my_db = MongoClient().test
778
+ fs = GridFSBucket(my_db)
779
+ # Get _id of file to read
780
+ file_id = fs.upload_from_stream("test_file", "data I want to store!")
781
+ # Get file to write to
782
+ file = open('myfile','wb+')
783
+ fs.download_to_stream(file_id, file)
784
+ file.seek(0)
785
+ contents = file.read()
786
+
787
+ Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.
788
+
789
+ :Parameters:
790
+ - `file_id`: The _id of the file to be downloaded.
791
+ - `destination`: a file-like object implementing :meth:`write`.
792
+ - `session` (optional): a
793
+ :class:`~pymongo.client_session.ClientSession`
794
+
795
+ .. versionchanged:: 3.6
796
+ Added ``session`` parameter.
797
+ """
798
+ with self.open_download_stream(file_id, session=session) as gout:
799
+ for chunk in gout:
800
+ destination.write(chunk)
801
+
802
+ @_csot.apply
803
+ def delete(self, file_id: Any, session: Optional[ClientSession] = None) -> None:
804
+ """Given an file_id, delete this stored file's files collection document
805
+ and associated chunks from a GridFS bucket.
806
+
807
+ For example::
808
+
809
+ my_db = MongoClient().test
810
+ fs = GridFSBucket(my_db)
811
+ # Get _id of file to delete
812
+ file_id = fs.upload_from_stream("test_file", "data I want to store!")
813
+ fs.delete(file_id)
814
+
815
+ Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.
816
+
817
+ :Parameters:
818
+ - `file_id`: The _id of the file to be deleted.
819
+ - `session` (optional): a
820
+ :class:`~pymongo.client_session.ClientSession`
821
+
822
+ .. versionchanged:: 3.6
823
+ Added ``session`` parameter.
824
+ """
825
+ _disallow_transactions(session)
826
+ res = self._files.delete_one({"_id": file_id}, session=session)
827
+ self._chunks.delete_many({"files_id": file_id}, session=session)
828
+ if not res.deleted_count:
829
+ raise NoFile("no file could be deleted because none matched %s" % file_id)
830
+
831
+ def find(self, *args: Any, **kwargs: Any) -> GridOutCursor:
832
+ """Find and return the files collection documents that match ``filter``
833
+
834
+ Returns a cursor that iterates across files matching
835
+ arbitrary queries on the files collection. Can be combined
836
+ with other modifiers for additional control.
837
+
838
+ For example::
839
+
840
+ for grid_data in fs.find({"filename": "lisa.txt"},
841
+ no_cursor_timeout=True):
842
+ data = grid_data.read()
843
+
844
+ would iterate through all versions of "lisa.txt" stored in GridFS.
845
+ Note that setting no_cursor_timeout to True may be important to
846
+ prevent the cursor from timing out during long multi-file processing
847
+ work.
848
+
849
+ As another example, the call::
850
+
851
+ most_recent_three = fs.find().sort("uploadDate", -1).limit(3)
852
+
853
+ would return a cursor to the three most recently uploaded files
854
+ in GridFS.
855
+
856
+ Follows a similar interface to
857
+ :meth:`~pymongo.collection.Collection.find`
858
+ in :class:`~pymongo.collection.Collection`.
859
+
860
+ If a :class:`~pymongo.client_session.ClientSession` is passed to
861
+ :meth:`find`, all returned :class:`~gridfs.grid_file.GridOut` instances
862
+ are associated with that session.
863
+
864
+ :Parameters:
865
+ - `filter`: Search query.
866
+ - `batch_size` (optional): The number of documents to return per
867
+ batch.
868
+ - `limit` (optional): The maximum number of documents to return.
869
+ - `no_cursor_timeout` (optional): The server normally times out idle
870
+ cursors after an inactivity period (10 minutes) to prevent excess
871
+ memory use. Set this option to True prevent that.
872
+ - `skip` (optional): The number of documents to skip before
873
+ returning.
874
+ - `sort` (optional): The order by which to sort results. Defaults to
875
+ None.
876
+ """
877
+ return GridOutCursor(self._collection, *args, **kwargs)
878
+
879
+ def open_download_stream_by_name(
880
+ self, filename: str, revision: int = -1, session: Optional[ClientSession] = None
881
+ ) -> GridOut:
882
+ """Opens a Stream from which the application can read the contents of
883
+ `filename` and optional `revision`.
884
+
885
+ For example::
886
+
887
+ my_db = MongoClient().test
888
+ fs = GridFSBucket(my_db)
889
+ grid_out = fs.open_download_stream_by_name("test_file")
890
+ contents = grid_out.read()
891
+
892
+ Returns an instance of :class:`~gridfs.grid_file.GridOut`.
893
+
894
+ Raises :exc:`~gridfs.errors.NoFile` if no such version of
895
+ that file exists.
896
+
897
+ Raises :exc:`~ValueError` filename is not a string.
898
+
899
+ :Parameters:
900
+ - `filename`: The name of the file to read from.
901
+ - `revision` (optional): Which revision (documents with the same
902
+ filename and different uploadDate) of the file to retrieve.
903
+ Defaults to -1 (the most recent revision).
904
+ - `session` (optional): a
905
+ :class:`~pymongo.client_session.ClientSession`
906
+
907
+ :Note: Revision numbers are defined as follows:
908
+
909
+ - 0 = the original stored file
910
+ - 1 = the first revision
911
+ - 2 = the second revision
912
+ - etc...
913
+ - -2 = the second most recent revision
914
+ - -1 = the most recent revision
915
+
916
+ .. versionchanged:: 3.6
917
+ Added ``session`` parameter.
918
+ """
919
+ validate_string("filename", filename)
920
+ query = {"filename": filename}
921
+ _disallow_transactions(session)
922
+ cursor = self._files.find(query, session=session)
923
+ if revision < 0:
924
+ skip = abs(revision) - 1
925
+ cursor.limit(-1).skip(skip).sort("uploadDate", DESCENDING)
926
+ else:
927
+ cursor.limit(-1).skip(revision).sort("uploadDate", ASCENDING)
928
+ try:
929
+ grid_file = next(cursor)
930
+ return GridOut(self._collection, file_document=grid_file, session=session)
931
+ except StopIteration:
932
+ raise NoFile("no version %d for filename %r" % (revision, filename))
933
+
934
+ @_csot.apply
935
+ def download_to_stream_by_name(
936
+ self,
937
+ filename: str,
938
+ destination: Any,
939
+ revision: int = -1,
940
+ session: Optional[ClientSession] = None,
941
+ ) -> None:
942
+ """Write the contents of `filename` (with optional `revision`) to
943
+ `destination`.
944
+
945
+ For example::
946
+
947
+ my_db = MongoClient().test
948
+ fs = GridFSBucket(my_db)
949
+ # Get file to write to
950
+ file = open('myfile','wb')
951
+ fs.download_to_stream_by_name("test_file", file)
952
+
953
+ Raises :exc:`~gridfs.errors.NoFile` if no such version of
954
+ that file exists.
955
+
956
+ Raises :exc:`~ValueError` if `filename` is not a string.
957
+
958
+ :Parameters:
959
+ - `filename`: The name of the file to read from.
960
+ - `destination`: A file-like object that implements :meth:`write`.
961
+ - `revision` (optional): Which revision (documents with the same
962
+ filename and different uploadDate) of the file to retrieve.
963
+ Defaults to -1 (the most recent revision).
964
+ - `session` (optional): a
965
+ :class:`~pymongo.client_session.ClientSession`
966
+
967
+ :Note: Revision numbers are defined as follows:
968
+
969
+ - 0 = the original stored file
970
+ - 1 = the first revision
971
+ - 2 = the second revision
972
+ - etc...
973
+ - -2 = the second most recent revision
974
+ - -1 = the most recent revision
975
+
976
+ .. versionchanged:: 3.6
977
+ Added ``session`` parameter.
978
+ """
979
+ with self.open_download_stream_by_name(filename, revision, session=session) as gout:
980
+ for chunk in gout:
981
+ destination.write(chunk)
982
+
983
+ def rename(
984
+ self, file_id: Any, new_filename: str, session: Optional[ClientSession] = None
985
+ ) -> None:
986
+ """Renames the stored file with the specified file_id.
987
+
988
+ For example::
989
+
990
+ my_db = MongoClient().test
991
+ fs = GridFSBucket(my_db)
992
+ # Get _id of file to rename
993
+ file_id = fs.upload_from_stream("test_file", "data I want to store!")
994
+ fs.rename(file_id, "new_test_name")
995
+
996
+ Raises :exc:`~gridfs.errors.NoFile` if no file with file_id exists.
997
+
998
+ :Parameters:
999
+ - `file_id`: The _id of the file to be renamed.
1000
+ - `new_filename`: The new name of the file.
1001
+ - `session` (optional): a
1002
+ :class:`~pymongo.client_session.ClientSession`
1003
+
1004
+ .. versionchanged:: 3.6
1005
+ Added ``session`` parameter.
1006
+ """
1007
+ _disallow_transactions(session)
1008
+ result = self._files.update_one(
1009
+ {"_id": file_id}, {"$set": {"filename": new_filename}}, session=session
1010
+ )
1011
+ if not result.matched_count:
1012
+ raise NoFile(
1013
+ "no files could be renamed %r because none "
1014
+ "matched file_id %i" % (new_filename, file_id)
1015
+ )