server_api.py 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. # Copyright 2020-present MongoDB, Inc.
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you
  4. # may not use this file except in compliance with the License. You
  5. # 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
  12. # implied. See the License for the specific language governing
  13. # permissions and limitations under the License.
  14. """Support for MongoDB Versioned API.
  15. .. _versioned-api-ref:
  16. MongoDB Versioned API
  17. =====================
  18. Starting in MongoDB 5.0, applications can specify the server API version
  19. to use when creating a :class:`~pymongo.mongo_client.MongoClient`. Doing so
  20. ensures that the driver behaves in a manner compatible with that server API
  21. version, regardless of the server's actual release version.
  22. Declaring an API Version
  23. ````````````````````````
  24. .. attention:: Versioned API requires MongoDB >=5.0.
  25. To configure MongoDB Versioned API, pass the ``server_api`` keyword option to
  26. :class:`~pymongo.mongo_client.MongoClient`::
  27. >>> from pymongo.mongo_client import MongoClient
  28. >>> from pymongo.server_api import ServerApi
  29. >>>
  30. >>> # Declare API version "1" for MongoClient "client"
  31. >>> server_api = ServerApi('1')
  32. >>> client = MongoClient(server_api=server_api)
  33. The declared API version is applied to all commands run through ``client``,
  34. including those sent through the generic
  35. :meth:`~pymongo.database.Database.command` helper.
  36. .. note:: Declaring an API version on the
  37. :class:`~pymongo.mongo_client.MongoClient` **and** specifying versioned
  38. API options in :meth:`~pymongo.database.Database.command` command document
  39. is not supported and will lead to undefined behaviour.
  40. To run any command without declaring a server API version or using a different
  41. API version, create a separate :class:`~pymongo.mongo_client.MongoClient`
  42. instance.
  43. Strict Mode
  44. ```````````
  45. Configuring ``strict`` mode will cause the MongoDB server to reject all
  46. commands that are not part of the declared :attr:`ServerApi.version`. This
  47. includes command options and aggregation pipeline stages.
  48. For example::
  49. >>> server_api = ServerApi('1', strict=True)
  50. >>> client = MongoClient(server_api=server_api)
  51. >>> client.test.command('count', 'test')
  52. Traceback (most recent call last):
  53. ...
  54. pymongo.errors.OperationFailure: Provided apiStrict:true, but the command count is not in API Version 1, full error: {'ok': 0.0, 'errmsg': 'Provided apiStrict:true, but the command count is not in API Version 1', 'code': 323, 'codeName': 'APIStrictError'
  55. Detecting API Deprecations
  56. ``````````````````````````
  57. The ``deprecationErrors`` option can be used to enable command failures
  58. when using functionality that is deprecated from the configured
  59. :attr:`ServerApi.version`. For example::
  60. >>> server_api = ServerApi('1', deprecation_errors=True)
  61. >>> client = MongoClient(server_api=server_api)
  62. Note that at the time of this writing, no deprecated APIs exist.
  63. Classes
  64. =======
  65. """
  66. class ServerApiVersion:
  67. """An enum that defines values for :attr:`ServerApi.version`.
  68. .. versionadded:: 3.12
  69. """
  70. V1 = "1"
  71. """Server API version "1"."""
  72. class ServerApi(object):
  73. """MongoDB Versioned API."""
  74. def __init__(self, version, strict=None, deprecation_errors=None):
  75. """Options to configure MongoDB Versioned API.
  76. :Parameters:
  77. - `version`: The API version string. Must be one of the values in
  78. :class:`ServerApiVersion`.
  79. - `strict` (optional): Set to ``True`` to enable API strict mode.
  80. Defaults to ``None`` which means "use the server's default".
  81. - `deprecation_errors` (optional): Set to ``True`` to enable
  82. deprecation errors. Defaults to ``None`` which means "use the
  83. server's default".
  84. .. versionadded:: 3.12
  85. """
  86. if version != ServerApiVersion.V1:
  87. raise ValueError("Unknown ServerApi version: %s" % (version,))
  88. if strict is not None and not isinstance(strict, bool):
  89. raise TypeError(
  90. "Wrong type for ServerApi strict, value must be an instance "
  91. "of bool, not %s" % (type(strict),))
  92. if (deprecation_errors is not None and
  93. not isinstance(deprecation_errors, bool)):
  94. raise TypeError(
  95. "Wrong type for ServerApi deprecation_errors, value must be "
  96. "an instance of bool, not %s" % (type(deprecation_errors),))
  97. self._version = version
  98. self._strict = strict
  99. self._deprecation_errors = deprecation_errors
  100. @property
  101. def version(self):
  102. """The API version setting.
  103. This value is sent to the server in the "apiVersion" field.
  104. """
  105. return self._version
  106. @property
  107. def strict(self):
  108. """The API strict mode setting.
  109. When set, this value is sent to the server in the "apiStrict" field.
  110. """
  111. return self._strict
  112. @property
  113. def deprecation_errors(self):
  114. """The API deprecation errors setting.
  115. When set, this value is sent to the server in the
  116. "apiDeprecationErrors" field.
  117. """
  118. return self._deprecation_errors
  119. def _add_to_command(cmd, server_api):
  120. """Internal helper which adds API versioning options to a command.
  121. :Parameters:
  122. - `cmd`: The command.
  123. - `server_api` (optional): A :class:`ServerApi` or ``None``.
  124. """
  125. if not server_api:
  126. return
  127. cmd['apiVersion'] = server_api.version
  128. if server_api.strict is not None:
  129. cmd['apiStrict'] = server_api.strict
  130. if server_api.deprecation_errors is not None:
  131. cmd['apiDeprecationErrors'] = server_api.deprecation_errors