def _update(self, filter, update, upsert, multi, **kwargs): validate_is_mapping("filter", filter) validate_boolean("upsert", upsert) if self.write_concern.acknowledged: updates = [ SON([('q', filter), ('u', update), ("upsert", upsert), ("multi", multi)]) ] command = SON([("update", self._collection_name), ("updates", updates), ("writeConcern", self.write_concern.document)]) raw_response = yield self._database.command(command, **kwargs) _check_write_command_response([[0, raw_response]]) # Extract upserted_id from returned array if raw_response.get("upserted"): raw_response["upserted"] = raw_response["upserted"][0]["_id"] else: yield self.update(filter, update, upsert=upsert, multi=multi, **kwargs) raw_response = None defer.returnValue(raw_response)
def _new_find_and_modify(self, filter, projection, sort, upsert=None, return_document=ReturnDocument.BEFORE, **kwargs): validate_is_mapping("filter", filter) if not isinstance(return_document, bool): raise ValueError("TxMongo: return_document must be ReturnDocument.BEFORE " "or ReturnDocument.AFTER") cmd = SON([("findAndModify", self._collection_name), ("query", filter), ("new", return_document)]) cmd.update(kwargs) if projection is not None: cmd["fields"] = self._normalize_fields_projection(projection) if sort is not None: cmd["sort"] = dict(sort["orderby"]) if upsert is not None: validate_boolean("upsert", upsert) cmd["upsert"] = upsert no_obj_error = "No matching object found" result = yield self._database.command(cmd, allowable_errors=[no_obj_error], **kwargs) defer.returnValue(result.get("value"))
def _parse_ssl_options(options): """Parse ssl options.""" use_ssl = options.get('ssl') if use_ssl is not None: validate_boolean('ssl', use_ssl) certfile = options.get('ssl_certfile') keyfile = options.get('ssl_keyfile') passphrase = options.get('ssl_pem_passphrase') ca_certs = options.get('ssl_ca_certs') cert_reqs = options.get('ssl_cert_reqs') match_hostname = options.get('ssl_match_hostname', True) crlfile = options.get('ssl_crlfile') ssl_kwarg_keys = [ k for k in options if k.startswith('ssl_') and options[k] ] if use_ssl == False and ssl_kwarg_keys: raise ConfigurationError("ssl has not been enabled but the " "following ssl parameters have been set: " "%s. Please set `ssl=True` or remove." % ', '.join(ssl_kwarg_keys)) if ssl_kwarg_keys and use_ssl is None: # ssl options imply ssl = True use_ssl = True if use_ssl is True: ctx = get_ssl_context(certfile, keyfile, passphrase, ca_certs, cert_reqs, crlfile, match_hostname) return ctx, match_hostname return None, match_hostname
def __init__(self, filter, replacement, upsert=False, collation=None): """Create a ReplaceOne instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :Parameters: - `filter`: A query that matches the document to replace. - `replacement`: The new document. - `upsert` (optional): If ``True``, perform an insert if no documents match the filter. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. This option is only supported on MongoDB 3.4 and above. .. versionchanged:: 3.5 Added the `collation` option. """ if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) self._filter = filter self._doc = replacement self._upsert = upsert self._collation = collation
def _parse_ssl_options(options): """Parse ssl options.""" use_ssl = options.get('ssl') if use_ssl is not None: validate_boolean('ssl', use_ssl) certfile = options.get('ssl_certfile') keyfile = options.get('ssl_keyfile') ca_certs = options.get('ssl_ca_certs') cert_reqs = options.get('ssl_cert_reqs') match_hostname = options.get('ssl_match_hostname', True) ssl_kwarg_keys = [k for k in options if k.startswith('ssl_') and options[k]] if use_ssl == False and ssl_kwarg_keys: raise ConfigurationError("ssl has not been enabled but the " "following ssl parameters have been set: " "%s. Please set `ssl=True` or remove." % ', '.join(ssl_kwarg_keys)) if cert_reqs and not ca_certs: raise ConfigurationError("If `ssl_cert_reqs` is not " "`ssl.CERT_NONE` then you must " "include `ssl_ca_certs` to be able " "to validate the server.") if ssl_kwarg_keys and use_ssl is None: # ssl options imply ssl = True use_ssl = True if use_ssl is True: ctx = get_ssl_context(certfile, keyfile, ca_certs, cert_reqs) return ctx, match_hostname return None, match_hostname
def _parse_ssl_options(options): """Parse ssl options.""" use_ssl = options.get('ssl') if use_ssl is not None: validate_boolean('ssl', use_ssl) certfile = options.get('ssl_certfile') keyfile = options.get('ssl_keyfile') passphrase = options.get('ssl_pem_passphrase') ca_certs = options.get('ssl_ca_certs') cert_reqs = options.get('ssl_cert_reqs') match_hostname = options.get('ssl_match_hostname', True) crlfile = options.get('ssl_crlfile') ssl_kwarg_keys = [k for k in options if k.startswith('ssl_') and options[k]] if use_ssl == False and ssl_kwarg_keys: raise ConfigurationError("ssl has not been enabled but the " "following ssl parameters have been set: " "%s. Please set `ssl=True` or remove." % ', '.join(ssl_kwarg_keys)) if ssl_kwarg_keys and use_ssl is None: # ssl options imply ssl = True use_ssl = True if use_ssl is True: ctx = get_ssl_context( certfile, keyfile, passphrase, ca_certs, cert_reqs, crlfile) return ctx, match_hostname return None, match_hostname
def __init__(self, filter=None, doc=None, upsert=None): if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) self._filter = filter self._doc = doc self._upsert = upsert
def count(self, with_limit_and_skip=False): """**DEPRECATED** - Get the size of the results set for this query. The :meth:`count` method is deprecated and **not** supported in a transaction. Please use :meth:`~pymongo.collection.Collection.count_documents` instead. Returns the number of documents in the results set for this query. Does not take :meth:`limit` and :meth:`skip` into account by default - set `with_limit_and_skip` to ``True`` if that is the desired behavior. Raises :class:`~pymongo.errors.OperationFailure` on a database error. When used with MongoDB >= 2.6, :meth:`~count` uses any :meth:`~hint` applied to the query. In the following example the hint is passed to the count command: collection.find({'field': 'value'}).hint('field_1').count() The :meth:`count` method obeys the :attr:`~pymongo.collection.Collection.read_preference` of the :class:`~pymongo.collection.Collection` instance on which :meth:`~pymongo.collection.Collection.find` was called. :Parameters: - `with_limit_and_skip` (optional): take any :meth:`limit` or :meth:`skip` that has been applied to this cursor into account when getting the count .. note:: The `with_limit_and_skip` parameter requires server version **>= 1.1.4-** .. versionchanged:: 3.7 Deprecated. .. versionchanged:: 2.8 The :meth:`~count` method now supports :meth:`~hint`. """ warnings.warn("count is deprecated. Use Collection.count_documents " "instead.", DeprecationWarning, stacklevel=2) validate_boolean("with_limit_and_skip", with_limit_and_skip) cmd = SON([("count", self.__collection.name), ("query", self.__spec)]) if self.__max_time_ms is not None: cmd["maxTimeMS"] = self.__max_time_ms if self.__comment: cmd["comment"] = self.__comment if self.__hint is not None: cmd["hint"] = self.__hint if with_limit_and_skip: if self.__limit: cmd["limit"] = self.__limit if self.__skip: cmd["skip"] = self.__skip return self.__collection._count( cmd, self.__collation, session=self.__session)
def _parse_ssl_options(options): """Parse ssl options.""" use_tls = options.get("tls") if use_tls is not None: validate_boolean("tls", use_tls) certfile = options.get("tlscertificatekeyfile") passphrase = options.get("tlscertificatekeyfilepassword") ca_certs = options.get("tlscafile") crlfile = options.get("tlscrlfile") allow_invalid_certificates = options.get("tlsallowinvalidcertificates", False) allow_invalid_hostnames = options.get("tlsallowinvalidhostnames", False) disable_ocsp_endpoint_check = options.get("tlsdisableocspendpointcheck", False) enabled_tls_opts = [] for opt in ( "tlscertificatekeyfile", "tlscertificatekeyfilepassword", "tlscafile", "tlscrlfile", ): # Any non-null value of these options implies tls=True. if opt in options and options[opt]: enabled_tls_opts.append(opt) for opt in ( "tlsallowinvalidcertificates", "tlsallowinvalidhostnames", "tlsdisableocspendpointcheck", ): # A value of False for these options implies tls=True. if opt in options and not options[opt]: enabled_tls_opts.append(opt) if enabled_tls_opts: if use_tls is None: # Implicitly enable TLS when one of the tls* options is set. use_tls = True elif not use_tls: # Error since tls is explicitly disabled but a tls option is set. raise ConfigurationError("TLS has not been enabled but the " "following tls parameters have been set: " "%s. Please set `tls=True` or remove." % ", ".join(enabled_tls_opts)) if use_tls: ctx = get_ssl_context( certfile, passphrase, ca_certs, crlfile, allow_invalid_certificates, allow_invalid_hostnames, disable_ocsp_endpoint_check, ) return ctx, allow_invalid_hostnames return None, allow_invalid_hostnames
def __init__(self, filter, doc, upsert, collation): if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) self._filter = filter self._doc = doc self._upsert = upsert self._collation = collation
def __init__(self, filter, doc, upsert, collation, array_filters): if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) if array_filters is not None: validate_list("array_filters", array_filters) self._filter = filter self._doc = doc self._upsert = upsert self._collation = collation self._array_filters = array_filters
def __init__(self, master, slaves=[], document_class=dict, tz_aware=False): """Create a new Master-Slave connection. The resultant connection should be interacted with using the same mechanisms as a regular `MongoClient`. The `MongoClient` instances used to create this `MasterSlaveConnection` can themselves make use of connection pooling, etc. `MongoClient` instances used as slaves should be created with the read_preference option set to :attr:`~pymongo.read_preferences.ReadPreference.SECONDARY`. Write concerns are inherited from `master` and can be changed in this instance. Raises TypeError if `master` is not an instance of `MongoClient` or slaves is not a list of at least one `MongoClient` instances. :Parameters: - `master`: `MongoClient` instance for the writable Master - `slaves`: list of `MongoClient` instances for the read-only slaves - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MasterSlaveConnection` will be timezone aware (otherwise they will be naive) """ if not isinstance(master, MongoClient): raise TypeError("master must be a MongoClient instance") if not isinstance(slaves, list) or len(slaves) == 0: raise TypeError("slaves must be a list of length >= 1") for slave in slaves: if not isinstance(slave, MongoClient): raise TypeError("slave %r is not an instance of MongoClient" % slave) warnings.warn( "MasterSlaveConnection is deprecated, and will be" " removed in PyMongo 3.0.", DeprecationWarning, stacklevel=2) validate_boolean('tz_aware', tz_aware) codec_options = CodecOptions(document_class, tz_aware) super(MasterSlaveConnection, self).__init__(read_preference=ReadPreference.SECONDARY, safe=master.safe, codec_options=codec_options, **master.write_concern) self.__master = master self.__slaves = slaves self.__request_counter = thread_util.Counter(master.use_greenlets)
def __init__(self, master, slaves=[], document_class=dict, tz_aware=False): """Create a new Master-Slave connection. The resultant connection should be interacted with using the same mechanisms as a regular `MongoClient`. The `MongoClient` instances used to create this `MasterSlaveConnection` can themselves make use of connection pooling, etc. `MongoClient` instances used as slaves should be created with the read_preference option set to :attr:`~pymongo.read_preferences.ReadPreference.SECONDARY`. Write concerns are inherited from `master` and can be changed in this instance. Raises TypeError if `master` is not an instance of `MongoClient` or slaves is not a list of at least one `MongoClient` instances. :Parameters: - `master`: `MongoClient` instance for the writable Master - `slaves`: list of `MongoClient` instances for the read-only slaves - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MasterSlaveConnection` will be timezone aware (otherwise they will be naive) """ if not isinstance(master, MongoClient): raise TypeError("master must be a MongoClient instance") if not isinstance(slaves, list) or len(slaves) == 0: raise TypeError("slaves must be a list of length >= 1") for slave in slaves: if not isinstance(slave, MongoClient): raise TypeError("slave %r is not an instance of MongoClient" % slave) warnings.warn("MasterSlaveConnection is deprecated, and will be" " removed in PyMongo 3.0.", DeprecationWarning, stacklevel=2) validate_boolean('tz_aware', tz_aware) codec_options = CodecOptions(document_class, tz_aware) super(MasterSlaveConnection, self).__init__(read_preference=ReadPreference.SECONDARY, safe=master.safe, codec_options=codec_options, **master.write_concern) self.__master = master self.__slaves = slaves self.__request_counter = thread_util.Counter(master.use_greenlets)
def add_user(self, name, password, read_only=False): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password`: the password of the user to create - `read_only` (optional): if ``True`` it will make user read only .. versionchanged:: 2.2 Added support for read only users .. versionadded:: 1.4 """ user = self.system.users.find_one({"user": name}) or {"user": name} user["pwd"] = helpers._password_digest(name, password) user["readOnly"] = common.validate_boolean('read_only', read_only) try: self.system.users.save(user, **self._get_wc_override()) except OperationFailure as e: # First admin user add fails gle in MongoDB >= 2.1.2 # See SERVER-4225 for more information. if 'login' in str(e): pass else: raise
def add_user(self, name, password, read_only=False): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password`: the password of the user to create - `read_only` (optional): if ``True`` it will make user read only .. versionchanged:: 2.2 Added support for read only users .. versionadded:: 1.4 """ user = self.system.users.find_one({"user": name}) or {"user": name} user["pwd"] = helpers._password_digest(name, password) user["readOnly"] = common.validate_boolean("read_only", read_only) try: self.system.users.save(user, safe=True) except OperationFailure, e: # First admin user add fails gle in MongoDB >= 2.1.2 # See SERVER-4225 for more information. if "login" in str(e): pass else: raise
def add_user(self, name, password=None, read_only=None, **kwargs): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password` (optional): the password of the user to create. Can not be used with the ``userSource`` argument. - `read_only` (optional): if ``True`` the user will be read only - `**kwargs` (optional): optional fields for the user document (e.g. ``userSource``, ``otherDBRoles``, or ``roles``). See `<http://docs.mongodb.org/manual/reference/privilege-documents>`_ for more information. .. note:: The use of optional keyword arguments like ``userSource``, ``otherDBRoles``, or ``roles`` requires MongoDB >= 2.4.0 .. versionchanged:: 2.5 Added kwargs support for optional fields introduced in MongoDB 2.4 .. versionchanged:: 2.2 Added support for read only users .. versionadded:: 1.4 """ if not isinstance(name, str): raise TypeError("name must be an instance " "of %s" % (str.__name__,)) if password is not None: if not isinstance(password, str): raise TypeError("password must be an instance " "of %s or None" % (str.__name__,)) if len(password) == 0: raise ValueError("password can't be empty") if read_only is not None: read_only = common.validate_boolean('read_only', read_only) if 'roles' in kwargs: raise ConfigurationError("Can not use " "read_only and roles together") try: uinfo = self.command("usersInfo", name, read_preference=ReadPreference.PRIMARY) self._create_or_update_user( (not uinfo["users"]), name, password, read_only, **kwargs) except OperationFailure as exc: # MongoDB >= 2.5.3 requires the use of commands to manage # users. if exc.code in common.COMMAND_NOT_FOUND_CODES: self._legacy_add_user(name, password, read_only, **kwargs) # Unauthorized. MongoDB >= 2.7.1 has a narrow localhost exception, # and we must add a user before sending commands. elif exc.code == 13: self._create_or_update_user( True, name, password, read_only, **kwargs) else: raise
def count(self, with_limit_and_skip=False): """Get the size of the results set for this query. Returns the number of documents in the results set for this query. Does not take :meth:`limit` and :meth:`skip` into account by default - set `with_limit_and_skip` to ``True`` if that is the desired behavior. Raises :class:`~pymongo.errors.OperationFailure` on a database error. When used with MongoDB >= 2.6, :meth:`~count` uses any :meth:`~hint` applied to the query. In the following example the hint is passed to the count command: collection.find({'field': 'value'}).hint('field_1').count() The :meth:`count` method obeys the :attr:`~pymongo.collection.Collection.read_preference` of the :class:`~pymongo.collection.Collection` instance on which :meth:`~pymongo.collection.Collection.find` was called. :Parameters: - `with_limit_and_skip` (optional): take any :meth:`limit` or :meth:`skip` that has been applied to this cursor into account when getting the count .. note:: The `with_limit_and_skip` parameter requires server version **>= 1.1.4-** .. versionchanged:: 2.8 The :meth:`~count` method now supports :meth:`~hint`. """ validate_boolean("with_limit_and_skip", with_limit_and_skip) options = {"query": self.__spec} if self.__max_time_ms is not None: options["maxTimeMS"] = self.__max_time_ms if self.__comment: options["$comment"] = self.__comment if self.__hint is not None: options["hint"] = self.__hint if with_limit_and_skip: if self.__limit: options["limit"] = self.__limit if self.__skip: options["skip"] = self.__skip return self.__collection.count(**options)
def __init__(self, filter, doc, upsert, collation, array_filters, hint): if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) if array_filters is not None: validate_list("array_filters", array_filters) if hint is not None: if not isinstance(hint, string_type): hint = helpers._index_document(hint) self._filter = filter self._doc = doc self._upsert = upsert self._collation = collation self._array_filters = array_filters self._hint = hint
def add_user(self, name, password=None, read_only=None, session=None, **kwargs): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password` (optional): the password of the user to create. Can not be used with the ``userSource`` argument. - `read_only` (optional): if ``True`` the user will be read only - `**kwargs` (optional): optional fields for the user document (e.g. ``userSource``, ``otherDBRoles``, or ``roles``). See `<http://docs.mongodb.org/manual/reference/privilege-documents>`_ for more information. - `session` (optional): a :class:`~pymongo.client_session.ClientSession`. .. versionchanged:: 3.6 Added ``session`` parameter. .. versionchanged:: 2.5 Added kwargs support for optional fields introduced in MongoDB 2.4 .. versionchanged:: 2.2 Added support for read only users """ if not isinstance(name, string_type): raise TypeError("name must be an " "instance of %s" % (string_type.__name__,)) if password is not None: if not isinstance(password, string_type): raise TypeError("password must be an " "instance of %s" % (string_type.__name__,)) if len(password) == 0: raise ValueError("password can't be empty") if read_only is not None: read_only = common.validate_boolean('read_only', read_only) if 'roles' in kwargs: raise ConfigurationError("Can not use " "read_only and roles together") try: uinfo = self.command("usersInfo", name, session=session) # Create the user if not found in uinfo, otherwise update one. self._create_or_update_user( (not uinfo["users"]), name, password, read_only, session=session, **kwargs) except OperationFailure as exc: # Unauthorized. Attempt to create the user in case of # localhost exception. if exc.code == 13: self._create_or_update_user( True, name, password, read_only, session=session, **kwargs) else: raise
def __init__( self, filter: Mapping[str, Any], replacement: Mapping[str, Any], upsert: bool = False, collation: Optional[_CollationIn] = None, hint: Optional[_IndexKeyHint] = None, ) -> None: """Create a ReplaceOne instance. For use with :meth:`~pymongo.collection.Collection.bulk_write`. :Parameters: - `filter`: A query that matches the document to replace. - `replacement`: The new document. - `upsert` (optional): If ``True``, perform an insert if no documents match the filter. - `collation` (optional): An instance of :class:`~pymongo.collation.Collation`. - `hint` (optional): An index to use to support the query predicate specified either by its string name, or in the same format as passed to :meth:`~pymongo.collection.Collection.create_index` (e.g. ``[('field', ASCENDING)]``). This option is only supported on MongoDB 4.2 and above. .. versionchanged:: 3.11 Added the ``hint`` option. .. versionchanged:: 3.5 Added the ``collation`` option. """ if filter is not None: validate_is_mapping("filter", filter) if upsert is not None: validate_boolean("upsert", upsert) if hint is not None: if not isinstance(hint, str): hint = helpers._index_document(hint) self._filter = filter self._doc = replacement self._upsert = upsert self._collation = collation self._hint = hint
async def count(self, with_limit_and_skip=False) -> int: """Get the size of the results set for this query. Returns the number of documents in the results set for this query. Does not take :meth:`limit` and :meth:`skip` into account by default - set `with_limit_and_skip` to ``True`` if that is the desired behavior. Raises :class:`~pymongo.errors.OperationFailure` on a database error. When used with MongoDB >= 2.6, :meth:`~count` uses any :meth:`~hint` applied to the query. In the following example the hint is passed to the count command: await collection.find({'field': 'value'}).hint('field_1').count() The :meth:`count` method obeys the :attr:`~aiomongo.collection.Collection.read_preference` of the :class:`~aiomongo.collection.Collection` instance on which :meth:`~aiomongo.collection.Collection.find` was called. :Parameters: - `with_limit_and_skip` (optional): take any :meth:`limit` or :meth:`skip` that has been applied to this cursor into account when getting the count """ validate_boolean('with_limit_and_skip', with_limit_and_skip) cmd = SON([('count', self.__collection.name), ('query', self.__spec)]) if self.__max_time_ms is not None: cmd['maxTimeMS'] = self.__max_time_ms if self.__comment: cmd['$comment'] = self.__comment if self.__hint is not None: cmd['hint'] = self.__hint if with_limit_and_skip: if self.__limit: cmd['limit'] = self.__limit if self.__skip: cmd['skip'] = self.__skip return await self.__collection._count(cmd, self.__collation)
def add_user(self, name, password=None, read_only=None, **kwargs): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password` (optional): the password of the user to create. Can not be used with the ``userSource`` argument. - `read_only` (optional): if ``True`` the user will be read only - `**kwargs` (optional): optional fields for the user document (e.g. ``userSource``, ``otherDBRoles``, or ``roles``). See `<http://docs.mongodb.org/manual/reference/privilege-documents>`_ for more information. .. note:: The use of optional keyword arguments like ``userSource``, ``otherDBRoles``, or ``roles`` requires MongoDB >= 2.4.0 .. versionchanged:: 2.5 Added kwargs support for optional fields introduced in MongoDB 2.4 .. versionchanged:: 2.2 Added support for read only users .. versionadded:: 1.4 """ if not isinstance(name, basestring): raise TypeError("name must be an instance " "of %s" % (basestring.__name__, )) if password is not None: if not isinstance(password, basestring): raise TypeError("password must be an instance " "of %s or None" % (basestring.__name__, )) if len(password) == 0: raise ValueError("password can't be empty") if read_only is not None: read_only = common.validate_boolean('read_only', read_only) if 'roles' in kwargs: raise ConfigurationError("Can not use " "read_only and roles together") try: uinfo = self.command("usersInfo", name) except OperationFailure, exc: # MongoDB >= 2.5.3 requires the use of commands to manage # users. "No such command" error didn't return an error # code (59) before MongoDB 2.4.7 so we assume that an error # code of None means the userInfo command doesn't exist and # we should fall back to the legacy add user code. if exc.code in (59, None): self._legacy_add_user(name, password, read_only, **kwargs) return raise
def add_user(self, name, password=None, read_only=None, **kwargs): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password` (optional): the password of the user to create. Can not be used with the ``userSource`` argument. - `read_only` (optional): if ``True`` the user will be read only - `**kwargs` (optional): optional fields for the user document (e.g. ``userSource``, ``otherDBRoles``, or ``roles``). See `<http://docs.mongodb.org/manual/reference/privilege-documents>`_ for more information. .. note:: The use of optional keyword arguments like ``userSource``, ``otherDBRoles``, or ``roles`` requires MongoDB >= 2.4.0 .. versionchanged:: 2.5 Added kwargs support for optional fields introduced in MongoDB 2.4 .. versionchanged:: 2.2 Added support for read only users .. versionadded:: 1.4 """ if not isinstance(name, basestring): raise TypeError("name must be an instance " "of %s" % (basestring.__name__,)) if password is not None: if not isinstance(password, basestring): raise TypeError("password must be an instance " "of %s or None" % (basestring.__name__,)) if len(password) == 0: raise ValueError("password can't be empty") if read_only is not None: read_only = common.validate_boolean('read_only', read_only) if 'roles' in kwargs: raise ConfigurationError("Can not use " "read_only and roles together") try: uinfo = self.command("usersInfo", name) except OperationFailure, exc: # MongoDB >= 2.5.3 requires the use of commands to manage # users. "No such command" error didn't return an error # code (59) before MongoDB 2.4.7 so we assume that an error # code of None means the userInfo command doesn't exist and # we should fall back to the legacy add user code. if exc.code in (59, None): self._legacy_add_user(name, password, read_only, **kwargs) return raise
def _update(self, filter, update, upsert, multi): validate_is_mapping("filter", filter) validate_boolean("upsert", upsert) if self.write_concern.acknowledged: updates = [SON([("q", filter), ("u", update), ("upsert", upsert), ("multi", multi)])] command = SON( [("update", self._collection_name), ("updates", updates), ("writeConcern", self.write_concern.document)] ) raw_response = yield self._database.command(command) _check_write_command_response([[0, raw_response]]) # Extract upserted_id from returned array if raw_response.get("upserted"): raw_response["upserted"] = raw_response["upserted"][0]["_id"] else: yield self.update(filter, update, upsert=upsert, multi=multi) raw_response = None defer.returnValue(raw_response)
def __init__(self, locale, caseLevel=None, caseFirst=None, strength=None, numericOrdering=None, alternate=None, maxVariable=None, normalization=None, backwards=None, **kwargs): locale = common.validate_string('locale', locale) self.__document = {'locale': locale} if caseLevel is not None: self.__document['caseLevel'] = common.validate_boolean( 'caseLevel', caseLevel) if caseFirst is not None: self.__document['caseFirst'] = common.validate_string( 'caseFirst', caseFirst) if strength is not None: self.__document['strength'] = common.validate_integer( 'strength', strength) if numericOrdering is not None: self.__document['numericOrdering'] = common.validate_boolean( 'numericOrdering', numericOrdering) if alternate is not None: self.__document['alternate'] = common.validate_string( 'alternate', alternate) if maxVariable is not None: self.__document['maxVariable'] = common.validate_string( 'maxVariable', maxVariable) if normalization is not None: self.__document['normalization'] = common.validate_boolean( 'normalization', normalization) if backwards is not None: self.__document['backwards'] = common.validate_boolean( 'backwards', backwards) self.__document.update(kwargs)
def __init__(self, locale: str, caseLevel: Optional[bool] = None, caseFirst: Optional[str] = None, strength: Optional[int] = None, numericOrdering: Optional[bool] = None, alternate: Optional[str] = None, maxVariable: Optional[str] = None, normalization: Optional[bool] = None, backwards: Optional[bool] = None, **kwargs: Any) -> None: locale = common.validate_string("locale", locale) self.__document: Dict[str, Any] = {"locale": locale} if caseLevel is not None: self.__document["caseLevel"] = common.validate_boolean( "caseLevel", caseLevel) if caseFirst is not None: self.__document["caseFirst"] = common.validate_string( "caseFirst", caseFirst) if strength is not None: self.__document["strength"] = common.validate_integer( "strength", strength) if numericOrdering is not None: self.__document["numericOrdering"] = common.validate_boolean( "numericOrdering", numericOrdering) if alternate is not None: self.__document["alternate"] = common.validate_string( "alternate", alternate) if maxVariable is not None: self.__document["maxVariable"] = common.validate_string( "maxVariable", maxVariable) if normalization is not None: self.__document["normalization"] = common.validate_boolean( "normalization", normalization) if backwards is not None: self.__document["backwards"] = common.validate_boolean( "backwards", backwards) self.__document.update(kwargs)
async def add_user(self, name: str, password: Optional[str] = None, read_only: Optional[bool] = None, **kwargs): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password` (optional): the password of the user to create. Can not be used with the ``userSource`` argument. - `read_only` (optional): if ``True`` the user will be read only - `**kwargs` (optional): optional fields for the user document (e.g. ``userSource``, ``otherDBRoles``, or ``roles``). See `<http://docs.mongodb.org/manual/reference/privilege-documents>`_ for more information. """ if not isinstance(name, str): raise TypeError('name must be an instance of str') if password is not None: if not isinstance(password, str): raise TypeError('password must be an instance of str') if len(password) == 0: raise ValueError('password can\'t be empty') if read_only is not None: read_only = common.validate_boolean('read_only', read_only) if 'roles' in kwargs: raise ConfigurationError('Can not use ' 'read_only and roles together') try: uinfo = await self.command('usersInfo', value=name) # Create the user if not found in uinfo, otherwise update one. await self._create_or_update_user((not uinfo['users']), name, password, read_only, **kwargs) except OperationFailure as exc: # Unauthorized. Attempt to create the user in case of # localhost exception. if exc.code == 13: await self._create_or_update_user(True, name, password, read_only, **kwargs) else: raise
def add_user(self, name, password=None, read_only=None, **kwargs): """Create user `name` with password `password`. Add a new user with permissions for this :class:`Database`. .. note:: Will change the password if user `name` already exists. :Parameters: - `name`: the name of the user to create - `password` (optional): the password of the user to create. Can not be used with the ``userSource`` argument. - `read_only` (optional): if ``True`` the user will be read only - `**kwargs` (optional): optional fields for the user document (e.g. ``userSource``, ``otherDBRoles``, or ``roles``). See `<http://docs.mongodb.org/manual/reference/privilege-documents>`_ for more information. .. note:: The use of optional keyword arguments like ``userSource``, ``otherDBRoles``, or ``roles`` requires MongoDB >= 2.4.0 .. versionchanged:: 2.5 Added kwargs support for optional fields introduced in MongoDB 2.4 .. versionchanged:: 2.2 Added support for read only users .. versionadded:: 1.4 """ user = self.system.users.find_one({"user": name}) or {"user": name} if password is not None: user["pwd"] = auth._password_digest(name, password) if read_only is not None: user["readOnly"] = common.validate_boolean('read_only', read_only) user.update(kwargs) try: self.system.users.save(user, **self._get_wc_override()) except OperationFailure, e: # First admin user add fails gle in MongoDB >= 2.1.2 # See SERVER-4225 for more information. if 'login' in str(e): pass else: raise
def _legacy_add_user(self, name, password, read_only, **kwargs): """Uses v1 system to add users, i.e. saving to system.users. """ user = self.system.users.find_one({"user": name}) or {"user": name} if password is not None: user["pwd"] = auth._password_digest(name, password) if read_only is not None: user["readOnly"] = common.validate_boolean('read_only', read_only) user.update(kwargs) try: self.system.users.save(user, **self._get_wc_override()) except OperationFailure, e: # First admin user add fails gle in MongoDB >= 2.1.2 # See SERVER-4225 for more information. if 'login' in str(e): pass else: raise
def __init__(self, hosts_or_uri=None, max_pool_size=10, document_class=dict, tz_aware=False, **kwargs): """Create a new connection to a MongoDB replica set. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `hosts_or_uri` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a string of `host:port` pairs (e.g. 'host1:port1,host2:port2'). If `hosts_or_uri` is None 'localhost:27017' will be used. :Parameters: - `hosts_or_uri` (optional): A MongoDB URI or string of `host:port` pairs. If a host is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `max_pool_size` (optional): The maximum size limit for each connection pool. - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`ReplicaSetConnection` will be timezone aware (otherwise they will be naive) - `replicaSet`: (required) The name of the replica set to connect to. The driver will verify that each host it connects to is a member of this replica set. Can be passed as a keyword argument or as a MongoDB URI option. Other optional parameters can be passed as keyword arguments: - `safe`: Use getlasterror for each write operation? - `j` or `journal`: Block until write operations have been commited to the journal. Ignored if the server is running without journaling. Implies safe=True. - `w`: (integer or string) If this is a replica set write operations won't return until they have been replicated to the specified number or tagged set of servers. Implies safe=True. - `wtimeoutMS`: Used in conjunction with `j` and/or `w`. Wait this many milliseconds for journal acknowledgement and/or write replication. Implies safe=True. - `fsync`: Force the database to fsync all files before returning When used with `j` the server awaits the next group commit before returning. Implies safe=True. - `socketTimeoutMS`: How long a send or receive on a socket can take before timing out. - `connectTimeoutMS`: How long a connection can take to be opened before timing out. - `ssl`: If True, create the connection to the servers using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.ReadPreference` for available options. - `auto_start_request`: If True (the default), each thread that accesses this :class:`ReplicaSetConnection` has a socket allocated to it for the thread's lifetime, for each member of the set. For :class:`~pymongo.ReadPreference` PRIMARY, auto_start_request=True ensures consistent reads, even if you read after an unsafe write. For read preferences other than PRIMARY, there are no consistency guarantees. (The semantics of auto_start_request, :class:`~pymongo.ReadPreference`, and :class:`ReplicaSetConnection` may change in future releases of PyMongo.) - `use_greenlets` (optional): if ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` - `slave_okay` or `slaveOk` (deprecated): Use `read_preference` instead. .. versionchanged:: 2.1.1+ Added `auto_start_request` option. .. versionadded:: 2.1 """ self.__opts = {} self.__seeds = set() self.__hosts = None self.__arbiters = set() self.__writer = None self.__readers = [] self.__pools = {} self.__index_cache = {} self.__auth_credentials = {} self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__document_class = document_class username = None db_name = None if hosts_or_uri is None: self.__seeds.add(('localhost', 27017)) elif '://' in hosts_or_uri: res = uri_parser.parse_uri(hosts_or_uri) self.__seeds.update(res['nodelist']) username = res['username'] password = res['password'] db_name = res['database'] self.__opts = res['options'] else: self.__seeds.update(uri_parser.split_hosts(hosts_or_uri)) for option, value in kwargs.iteritems(): option, value = common.validate(option, value) self.__opts[option] = value if self.__opts.get('use_greenlets', False): if not pool.have_greenlet: raise ConfigurationError( "The greenlet module is not available. " "Install the greenlet package from PyPI." ) self.pool_class = pool.GreenletPool else: self.pool_class = pool.Pool self.__auto_start_request = self.__opts.get('auto_start_request', True) self.__in_request = self.__auto_start_request self.__name = self.__opts.get('replicaset') if not self.__name: raise ConfigurationError("the replicaSet " "keyword parameter is required.") self.__net_timeout = self.__opts.get('sockettimeoutms') self.__conn_timeout = self.__opts.get('connecttimeoutms') self.__use_ssl = self.__opts.get('ssl', False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") super(ReplicaSetConnection, self).__init__(**self.__opts) if self.slave_okay: warnings.warn("slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) self.refresh() monitor_thread = Monitor(self) monitor_thread.setName("ReplicaSetMonitorThread") monitor_thread.setDaemon(True) monitor_thread.start() if db_name and username is None: warnings.warn("must provide a username and password " "to authenticate to %s" % (db_name,)) if username: db_name = db_name or 'admin' if not self[db_name].authenticate(username, password): raise ConfigurationError("authentication failed")
def __init__(self, host=None, port=None, max_pool_size=10, document_class=dict, tz_aware=False, _connect=True, **kwargs): """Create a new connection to a single MongoDB instance at *host:port*. The resultant client object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`TypeError` if port is not an instance of ``int``. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `host` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. Any port specified in the host string(s) will override the `port` parameter. If multiple mongodb URIs containing database or auth information are passed, the last database, username, and password present will be used. For username and passwords reserved characters like ':', '/', '+' and '@' must be escaped following RFC 2396. :Parameters: - `host` (optional): hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `port` (optional): port number on which to connect - `max_pool_size` (optional): The maximum number of idle connections to keep open in the pool for future use - `document_class` (optional): default class to use for documents returned from queries on this client - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MongoClient` will be timezone aware (otherwise they will be naive) | **Other optional parameters can be passed as keyword arguments:** - `socketTimeoutMS`: (integer) How long (in milliseconds) a send or receive on a socket can take before timing out. - `connectTimeoutMS`: (integer) How long (in milliseconds) a connection can take to be opened before timing out. - `auto_start_request`: If ``True``, each thread that accesses this :class:`MongoClient` has a socket allocated to it for the thread's lifetime. This ensures consistent reads, even if you read after an unacknowledged write. Defaults to ``False`` - `use_greenlets`: If ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` | **Write Concern options:** - `w`: (integer or string) If this is a replica set, write operations will block until they have been replicated to the specified number or tagged set of servers. `w=<int>` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). Passing w=0 **disables write acknowledgement** and all other write concern options. - `wtimeout`: (integer) Used in conjunction with `w`. Specify a value in milliseconds to control how long to wait for write propagation to complete. If replication does not complete in the given timeframe, a timeout exception is raised. - `j`: If ``True`` block until write operations have been committed to the journal. Ignored if the server is running without journaling. - `fsync`: If ``True`` force the database to fsync all files before returning. When used with `j` the server awaits the next group commit before returning. | **Replica set keyword arguments for connecting with a replica set - either directly or via a mongos:** | (ignored by standalone mongod instances) - `replicaSet`: (string) The name of the replica set to connect to. The driver will verify that the replica set it connects to matches this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. *Ignored by mongos*. - `read_preference`: The read preference for this client. If connecting to a secondary then a read preference mode *other* than PRIMARY is required - otherwise all queries will throw :class:`~pymongo.errors.AutoReconnect` "not master". See :class:`~pymongo.read_preferences.ReadPreference` for all available read preference options. - `tag_sets`: Ignored unless connecting to a replica set via mongos. Specify a priority-order for tag sets, provide a list of tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag set, ``{}``, means "read from any member that matches the mode, ignoring tags. | **SSL configuration:** - `ssl`: If ``True``, create the connection to the server using SSL. - `ssl_keyfile`: The private keyfile used to identify the local connection against mongod. If included with the ``certfile` then only the ``ssl_certfile`` is needed. Implies ``ssl=True``. - `ssl_certfile`: The certificate file used to identify the local connection against mongod. Implies ``ssl=True``. - `ssl_cert_reqs`: Specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided. It must be one of the three values ``ssl.CERT_NONE`` (certificates ignored), ``ssl.CERT_OPTIONAL`` (not required, but validated if provided), or ``ssl.CERT_REQUIRED`` (required and validated). If the value of this parameter is not ``ssl.CERT_NONE``, then the ``ssl_ca_certs`` parameter must point to a file of CA certificates. Implies ``ssl=True``. - `ssl_ca_certs`: The ca_certs file contains a set of concatenated "certification authority" certificates, which are used to validate certificates passed from the other end of the connection. Implies ``ssl=True``. .. seealso:: :meth:`end_request` .. mongodoc:: connections .. versionchanged:: 2.5 Added additional ssl options .. versionadded:: 2.4 """ if host is None: host = self.HOST if isinstance(host, basestring): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") seeds = set() username = None password = None db_name = None opts = {} for entity in host: if "://" in entity: if entity.startswith("mongodb://"): res = uri_parser.parse_uri(entity, port) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password db_name = res["database"] or db_name opts = res["options"] else: idx = entity.find("://") raise InvalidURI("Invalid URI scheme: " "%s" % (entity[:idx],)) else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") self.__nodes = seeds self.__host = None self.__port = None self.__is_primary = False self.__is_mongos = False # _pool_class option is for deep customization of PyMongo, e.g. Motor. # SHOULD NOT BE USED BY DEVELOPERS EXTERNAL TO 10GEN. pool_class = kwargs.pop('_pool_class', pool.Pool) options = {} for option, value in kwargs.iteritems(): option, value = common.validate(option, value) options[option] = value options.update(opts) self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__cursor_manager = CursorManager(self) self.__repl = options.get('replicaset') if len(seeds) == 1 and not self.__repl: self.__direct = True else: self.__direct = False self.__nodes = set() self.__net_timeout = options.get('sockettimeoutms') self.__conn_timeout = options.get('connecttimeoutms') self.__use_ssl = options.get('ssl', None) self.__ssl_keyfile = options.get('ssl_keyfile', None) self.__ssl_certfile = options.get('ssl_certfile', None) self.__ssl_cert_reqs = options.get('ssl_cert_reqs', None) self.__ssl_ca_certs = options.get('ssl_ca_certs', None) ssl_kwarg_keys = [k for k in kwargs.keys() if k.startswith('ssl_')] if self.__use_ssl == False and ssl_kwarg_keys: raise ConfigurationError("ssl has not been enabled but the " "following ssl parameters have been set: " "%s. Please set `ssl=True` or remove." % ', '.join(ssl_kwarg_keys)) if self.__ssl_cert_reqs and not self.__ssl_ca_certs: raise ConfigurationError("If `ssl_cert_reqs` is not " "`ssl.CERT_NONE` then you must " "include `ssl_ca_certs` to be able " "to validate the server.") if ssl_kwarg_keys and self.__use_ssl is None: # ssl options imply ssl = True self.__use_ssl = True if self.__use_ssl and not HAS_SSL: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") self.__use_greenlets = options.get('use_greenlets', False) self.__pool = pool_class( None, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl, use_greenlets=self.__use_greenlets, ssl_keyfile=self.__ssl_keyfile, ssl_certfile=self.__ssl_certfile, ssl_cert_reqs=self.__ssl_cert_reqs, ssl_ca_certs=self.__ssl_ca_certs) self.__document_class = document_class self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__auto_start_request = options.get('auto_start_request', False) # cache of existing indexes used by ensure_index ops self.__index_cache = {} self.__auth_credentials = {} super(MongoClient, self).__init__(**options) if self.slave_okay: warnings.warn("slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning, stacklevel=2) if _connect: try: self.__find_node(seeds) except AutoReconnect, e: # ConnectionFailure makes more sense here than AutoReconnect raise ConnectionFailure(str(e))
def __init__(self, hosts_or_uri=None, max_pool_size=10, document_class=dict, tz_aware=False, **kwargs): """Create a new connection to a MongoDB replica set. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `hosts_or_uri` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a string of `host:port` pairs (e.g. 'host1:port1,host2:port2'). If `hosts_or_uri` is None 'localhost:27017' will be used. .. note:: Instances of :class:`~ReplicaSetConnection` start a background task to monitor the state of the replica set. This allows it to quickly respond to changes in replica set configuration. Before discarding an instance of :class:`~ReplicaSetConnection` make sure you call :meth:`~close` to ensure that the monitor task is cleanly shut down. :Parameters: - `hosts_or_uri` (optional): A MongoDB URI or string of `host:port` pairs. If a host is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `max_pool_size` (optional): The maximum size limit for each connection pool. - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`ReplicaSetConnection` will be timezone aware (otherwise they will be naive) - `replicaSet`: (required) The name of the replica set to connect to. The driver will verify that each host it connects to is a member of this replica set. Can be passed as a keyword argument or as a MongoDB URI option. Other optional parameters can be passed as keyword arguments: - `safe`: Use getlasterror for each write operation? - `j` or `journal`: Block until write operations have been commited to the journal. Ignored if the server is running without journaling. Implies safe=True. - `w`: (integer or string) If this is a replica set write operations won't return until they have been replicated to the specified number or tagged set of servers. Implies safe=True. - `wtimeoutMS`: Used in conjunction with `j` and/or `w`. Wait this many milliseconds for journal acknowledgement and/or write replication. Implies safe=True. - `fsync`: Force the database to fsync all files before returning When used with `j` the server awaits the next group commit before returning. Implies safe=True. - `socketTimeoutMS`: How long a send or receive on a socket can take before timing out. - `connectTimeoutMS`: How long a connection can take to be opened before timing out. - `ssl`: If True, create the connection to the servers using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.ReadPreference` for available options. - `auto_start_request`: If True (the default), each thread that accesses this :class:`ReplicaSetConnection` has a socket allocated to it for the thread's lifetime, for each member of the set. For :class:`~pymongo.ReadPreference` PRIMARY, auto_start_request=True ensures consistent reads, even if you read after an unsafe write. For read preferences other than PRIMARY, there are no consistency guarantees. (The semantics of auto_start_request, :class:`~pymongo.ReadPreference`, and :class:`ReplicaSetConnection` may change in future releases of PyMongo.) - `use_greenlets` (optional): if ``True``, use a background Greenlet instead of a background thread to monitor state of replica set. :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()`. `use_greenlets` with ReplicaSetConnection requires `Gevent <http://gevent.org/>`_ to be installed. - `slave_okay` or `slaveOk` (deprecated): Use `read_preference` instead. - `host`: For compatibility with connection.Connection. If both `host` and `hosts_or_uri` are specified `host` takes precedence. - `port`: For compatibility with connection.Connection. The default port number to use for hosts. - `network_timeout`: For compatibility with connection.Connection. The timeout (in seconds) to use for socket operations - default is no timeout. If both `network_timeout` and `socketTimeoutMS` are are specified `network_timeout` takes precedence, matching connection.Connection. .. versionchanged:: 2.2 Added `auto_start_request` and `use_greenlets` options. Added support for `host`, `port`, and `network_timeout` keyword arguments for compatibility with connection.Connection. .. versionadded:: 2.1 """ self.__opts = {} self.__seeds = set() self.__hosts = None self.__arbiters = set() self.__writer = None self.__readers = [] self.__pools = {} self.__index_cache = {} self.__auth_credentials = {} self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__document_class = document_class # Compatibility with connection.Connection host = kwargs.pop('host', hosts_or_uri) port = kwargs.pop('port', 27017) if not isinstance(port, int): raise TypeError("port must be an instance of int") network_timeout = kwargs.pop('network_timeout', None) if network_timeout is not None: if (not isinstance(network_timeout, (int, float)) or network_timeout <= 0): raise ConfigurationError("network_timeout must " "be a positive integer") username = None db_name = None if host is None: self.__seeds.add(('localhost', port)) elif '://' in host: res = uri_parser.parse_uri(host, port) self.__seeds.update(res['nodelist']) username = res['username'] password = res['password'] db_name = res['database'] self.__opts = res['options'] else: self.__seeds.update(uri_parser.split_hosts(host, port)) for option, value in kwargs.iteritems(): option, value = common.validate(option, value) self.__opts[option] = value if self.__opts.get('use_greenlets', False): if not have_gevent: raise ConfigurationError( "The gevent module is not available. " "Install the gevent package from PyPI.") self.pool_class = pool.GreenletPool else: self.pool_class = pool.Pool self.__auto_start_request = self.__opts.get('auto_start_request', True) self.__in_request = self.__auto_start_request self.__name = self.__opts.get('replicaset') if not self.__name: raise ConfigurationError("the replicaSet " "keyword parameter is required.") self.__net_timeout = (network_timeout or self.__opts.get('sockettimeoutms')) self.__conn_timeout = self.__opts.get('connecttimeoutms') self.__use_ssl = self.__opts.get('ssl', False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") super(ReplicaSetConnection, self).__init__(**self.__opts) if self.slave_okay: warnings.warn( "slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) self.refresh() if db_name and username is None: warnings.warn("must provide a username and password " "to authenticate to %s" % (db_name, )) if username: db_name = db_name or 'admin' if not self[db_name].authenticate(username, password): raise ConfigurationError("authentication failed") # Start the monitor after we know the configuration is correct. if self.__opts.get('use_greenlets', False): self.__monitor = MonitorGreenlet(self) else: # NOTE: Don't ever make this a daemon thread in CPython. Daemon # threads in CPython cause serious issues when the interpreter is # torn down. Symptoms range from random exceptions to the # interpreter dumping core. self.__monitor = MonitorThread(self) # Sadly, weakrefs aren't totally reliable in PyPy and Jython # so use a daemon thread there. if (sys.platform.startswith('java') or 'PyPy' in sys.version): self.__monitor.setDaemon(True) self.__monitor.start()
def __init__(self, hosts_or_uri=None, max_pool_size=10, document_class=dict, tz_aware=False, **kwargs): """Create a new connection to a MongoDB replica set. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `hosts_or_uri` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a string of `host:port` pairs (e.g. 'host1:port1,host2:port2'). If `hosts_or_uri` is None 'localhost:27017' will be used. :Parameters: - `hosts_or_uri` (optional): A MongoDB URI or string of `host:port` pairs. If a host is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `max_pool_size` (optional): The maximum size limit for each connection pool. - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`ReplicaSetConnection` will be timezone aware (otherwise they will be naive) - `replicaSet`: (required) The name of the replica set to connect to. The driver will verify that each host it connects to is a member of this replica set. Can be passed as a keyword argument or as a MongoDB URI option. Other optional parameters can be passed as keyword arguments: - `safe`: Use getlasterror for each write operation? - `j` or `journal`: Block until write operations have been commited to the journal. Ignored if the server is running without journaling. Implies safe=True. - `w`: (integer or string) If this is a replica set write operations won't return until they have been replicated to the specified number or tagged set of servers. Implies safe=True. - `wtimeoutMS`: Used in conjunction with `j` and/or `w`. Wait this many milliseconds for journal acknowledgement and/or write replication. Implies safe=True. - `fsync`: Force the database to fsync all files before returning When used with `j` the server awaits the next group commit before returning. Implies safe=True. - `socketTimeoutMS`: How long a send or receive on a socket can take before timing out. - `connectTimeoutMS`: How long a connection can take to be opened before timing out. - `ssl`: If True, create the connection to the servers using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.ReadPreference` for available options. - `auto_start_request`: If True (the default), each thread that accesses this :class:`ReplicaSetConnection` has a socket allocated to it for the thread's lifetime, for each member of the set. For :class:`~pymongo.ReadPreference` PRIMARY, auto_start_request=True ensures consistent reads, even if you read after an unsafe write. For read preferences other than PRIMARY, there are no consistency guarantees. (The semantics of auto_start_request, :class:`~pymongo.ReadPreference`, and :class:`ReplicaSetConnection` may change in future releases of PyMongo.) - `use_greenlets` (optional): if ``True``, use a background Greenlet instead of a background thread to monitor state of replica set. :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()`. `use_greenlets` with ReplicaSetConnection requires `Gevent <http://gevent.org/>`_ to be installed. - `slave_okay` or `slaveOk` (deprecated): Use `read_preference` instead. - `host`: For compatibility with connection.Connection. If both `host` and `hosts_or_uri` are specified `host` takes precedence. - `port`: For compatibility with connection.Connection. The default port number to use for hosts. - `network_timeout`: For compatibility with connection.Connection. The timeout (in seconds) to use for socket operations - default is no timeout. If both `network_timeout` and `socketTimeoutMS` are are specified `network_timeout` takes precedence, matching connection.Connection. .. versionchanged:: 2.2 Added `auto_start_request` and `use_greenlets` options. Added support for `host`, `port`, and `network_timeout` keyword arguments for compatibility with connection.Connection. .. versionadded:: 2.1 """ self.__opts = {} self.__seeds = set() self.__hosts = None self.__arbiters = set() self.__writer = None self.__readers = [] self.__pools = {} self.__index_cache = {} self.__auth_credentials = {} self.__max_pool_size = common.validate_positive_integer("max_pool_size", max_pool_size) self.__tz_aware = common.validate_boolean("tz_aware", tz_aware) self.__document_class = document_class # Compatibility with connection.Connection host = kwargs.pop("host", hosts_or_uri) port = kwargs.pop("port", 27017) if not isinstance(port, int): raise TypeError("port must be an instance of int") network_timeout = kwargs.pop("network_timeout", None) if network_timeout is not None: if not isinstance(network_timeout, (int, float)) or network_timeout <= 0: raise ConfigurationError("network_timeout must " "be a positive integer") username = None db_name = None if host is None: self.__seeds.add(("localhost", port)) elif "://" in host: res = uri_parser.parse_uri(host, port) self.__seeds.update(res["nodelist"]) username = res["username"] password = res["password"] db_name = res["database"] self.__opts = res["options"] else: self.__seeds.update(uri_parser.split_hosts(host, port)) for option, value in kwargs.iteritems(): option, value = common.validate(option, value) self.__opts[option] = value if self.__opts.get("use_greenlets", False): if not have_gevent: raise ConfigurationError("The gevent module is not available. " "Install the gevent package from PyPI.") self.pool_class = pool.GreenletPool else: self.pool_class = pool.Pool self.__auto_start_request = self.__opts.get("auto_start_request", True) self.__in_request = self.__auto_start_request self.__name = self.__opts.get("replicaset") if not self.__name: raise ConfigurationError("the replicaSet " "keyword parameter is required.") self.__net_timeout = network_timeout or self.__opts.get("sockettimeoutms") self.__conn_timeout = self.__opts.get("connecttimeoutms") self.__use_ssl = self.__opts.get("ssl", False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError( "The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI." ) super(ReplicaSetConnection, self).__init__(**self.__opts) if self.slave_okay: warnings.warn("slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) self.refresh() if db_name and username is None: warnings.warn("must provide a username and password " "to authenticate to %s" % (db_name,)) if username: db_name = db_name or "admin" if not self[db_name].authenticate(username, password): raise ConfigurationError("authentication failed") # Start the monitor after we know the configuration is correct. if self.__opts.get("use_greenlets", False): monitor = GreenletMonitor(self) else: # NOTE: Don't ever make this a daemon thread in CPython. Daemon # threads in CPython cause serious issues when the interpreter is # torn down. Symptoms range from random exceptions to the # interpreter dumping core. monitor = Monitor(self) monitor.setName("ReplicaSetMonitorThread") # Sadly, weakrefs aren't totally reliable in PyPy and Jython # so use a daemon thread there. if sys.platform.startswith("java") or "PyPy" in sys.version: monitor.setDaemon(True) monitor.start()
def __init__( self, collection: "Collection[_DocumentType]", filter: Optional[Mapping[str, Any]] = None, projection: Optional[Union[Mapping[str, Any], Iterable[str]]] = None, skip: int = 0, limit: int = 0, no_cursor_timeout: bool = False, cursor_type: int = CursorType.NON_TAILABLE, sort: Optional[_Sort] = None, allow_partial_results: bool = False, oplog_replay: bool = False, batch_size: int = 0, collation: Optional[_CollationIn] = None, hint: Optional[_Hint] = None, max_scan: Optional[int] = None, max_time_ms: Optional[int] = None, max: Optional[_Sort] = None, min: Optional[_Sort] = None, return_key: Optional[bool] = None, show_record_id: Optional[bool] = None, snapshot: Optional[bool] = None, comment: Optional[Any] = None, session: Optional["ClientSession"] = None, allow_disk_use: Optional[bool] = None, let: Optional[bool] = None, ) -> None: """Create a new cursor. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find` instead. .. seealso:: The MongoDB documentation on `cursors <https://dochub.mongodb.org/core/cursors>`_. """ # Initialize all attributes used in __del__ before possibly raising # an error to avoid attribute errors during garbage collection. self.__collection: Collection[_DocumentType] = collection self.__id: Any = None self.__exhaust = False self.__sock_mgr: Any = None self.__killed = False self.__session: Optional["ClientSession"] if session: self.__session = session self.__explicit_session = True else: self.__session = None self.__explicit_session = False spec: Mapping[str, Any] = filter or {} validate_is_mapping("filter", spec) if not isinstance(skip, int): raise TypeError("skip must be an instance of int") if not isinstance(limit, int): raise TypeError("limit must be an instance of int") validate_boolean("no_cursor_timeout", no_cursor_timeout) if no_cursor_timeout and not self.__explicit_session: warnings.warn( "use an explicit session with no_cursor_timeout=True " "otherwise the cursor may still timeout after " "30 minutes, for more info see " "https://docs.mongodb.com/v4.4/reference/method/" "cursor.noCursorTimeout/" "#session-idle-timeout-overrides-nocursortimeout", UserWarning, stacklevel=2, ) if cursor_type not in ( CursorType.NON_TAILABLE, CursorType.TAILABLE, CursorType.TAILABLE_AWAIT, CursorType.EXHAUST, ): raise ValueError("not a valid value for cursor_type") validate_boolean("allow_partial_results", allow_partial_results) validate_boolean("oplog_replay", oplog_replay) if not isinstance(batch_size, int): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") # Only set if allow_disk_use is provided by the user, else None. if allow_disk_use is not None: allow_disk_use = validate_boolean("allow_disk_use", allow_disk_use) if projection is not None: projection = helpers._fields_list_to_dict(projection, "projection") if let is not None: validate_is_document_type("let", let) self.__let = let self.__spec = spec self.__has_filter = filter is not None self.__projection = projection self.__skip = skip self.__limit = limit self.__batch_size = batch_size self.__ordering = sort and helpers._index_document(sort) or None self.__max_scan = max_scan self.__explain = False self.__comment = comment self.__max_time_ms = max_time_ms self.__max_await_time_ms: Optional[int] = None self.__max: Optional[Union[SON[Any, Any], _Sort]] = max self.__min: Optional[Union[SON[Any, Any], _Sort]] = min self.__collation = validate_collation_or_none(collation) self.__return_key = return_key self.__show_record_id = show_record_id self.__allow_disk_use = allow_disk_use self.__snapshot = snapshot self.__set_hint(hint) # Exhaust cursor support if cursor_type == CursorType.EXHAUST: if self.__collection.database.client.is_mongos: raise InvalidOperation( "Exhaust cursors are not supported by mongos") if limit: raise InvalidOperation("Can't use limit and exhaust together.") self.__exhaust = True # This is ugly. People want to be able to do cursor[5:5] and # get an empty result set (old behavior was an # exception). It's hard to do that right, though, because the # server uses limit(0) to mean 'no limit'. So we set __empty # in that case and check for it when iterating. We also unset # it anytime we change __limit. self.__empty = False self.__data: deque = deque() self.__address = None self.__retrieved = 0 self.__codec_options = collection.codec_options # Read preference is set when the initial find is sent. self.__read_preference = None self.__read_concern = collection.read_concern self.__query_flags = cursor_type if no_cursor_timeout: self.__query_flags |= _QUERY_OPTIONS["no_timeout"] if allow_partial_results: self.__query_flags |= _QUERY_OPTIONS["partial"] if oplog_replay: self.__query_flags |= _QUERY_OPTIONS["oplog_replay"] # The namespace to use for find/getMore commands. self.__dbname = collection.database.name self.__collname = collection.name
def __init__(self, collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, batch_size=0, collation=None, hint=None, max_scan=None, max_time_ms=None, max=None, min=None, return_key=False, show_record_id=False, snapshot=False, comment=None, session=None, allow_disk_use=None): """Create a new cursor. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find` instead. .. mongodoc:: cursors """ # Initialize all attributes used in __del__ before possibly raising # an error to avoid attribute errors during garbage collection. self.__id = None self.__exhaust = False self.__exhaust_mgr = None self.__killed = False if session: self.__session = session self.__explicit_session = True else: self.__session = None self.__explicit_session = False spec = filter if spec is None: spec = {} validate_is_mapping("filter", spec) if not isinstance(skip, int): raise TypeError("skip must be an instance of int") if not isinstance(limit, int): raise TypeError("limit must be an instance of int") validate_boolean("no_cursor_timeout", no_cursor_timeout) if no_cursor_timeout and not self.__explicit_session: warnings.warn( "use an explicit session with no_cursor_timeout=True " "otherwise the cursor may still timeout after " "30 minutes, for more info see " "https://docs.mongodb.com/v4.4/reference/method/" "cursor.noCursorTimeout/" "#session-idle-timeout-overrides-nocursortimeout", UserWarning, stacklevel=2) if cursor_type not in (CursorType.NON_TAILABLE, CursorType.TAILABLE, CursorType.TAILABLE_AWAIT, CursorType.EXHAUST): raise ValueError("not a valid value for cursor_type") validate_boolean("allow_partial_results", allow_partial_results) validate_boolean("oplog_replay", oplog_replay) if modifiers is not None: warnings.warn("the 'modifiers' parameter is deprecated", DeprecationWarning, stacklevel=2) validate_is_mapping("modifiers", modifiers) if not isinstance(batch_size, int): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") # Only set if allow_disk_use is provided by the user, else None. if allow_disk_use is not None: allow_disk_use = validate_boolean("allow_disk_use", allow_disk_use) if projection is not None: if not projection: projection = {"_id": 1} projection = helpers._fields_list_to_dict(projection, "projection") self.__collection = collection self.__spec = spec self.__projection = projection self.__skip = skip self.__limit = limit self.__batch_size = batch_size self.__modifiers = modifiers and modifiers.copy() or {} self.__ordering = sort and helpers._index_document(sort) or None self.__max_scan = max_scan self.__explain = False self.__comment = comment self.__max_time_ms = max_time_ms self.__max_await_time_ms = None self.__max = max self.__min = min self.__collation = validate_collation_or_none(collation) self.__return_key = return_key self.__show_record_id = show_record_id self.__allow_disk_use = allow_disk_use self.__snapshot = snapshot self.__set_hint(hint) # Exhaust cursor support if cursor_type == CursorType.EXHAUST: if self.__collection.database.client.is_mongos: raise InvalidOperation('Exhaust cursors are ' 'not supported by mongos') if limit: raise InvalidOperation("Can't use limit and exhaust together.") self.__exhaust = True # This is ugly. People want to be able to do cursor[5:5] and # get an empty result set (old behavior was an # exception). It's hard to do that right, though, because the # server uses limit(0) to mean 'no limit'. So we set __empty # in that case and check for it when iterating. We also unset # it anytime we change __limit. self.__empty = False self.__data = deque() self.__address = None self.__retrieved = 0 self.__codec_options = collection.codec_options # Read preference is set when the initial find is sent. self.__read_preference = None self.__read_concern = collection.read_concern self.__query_flags = cursor_type if no_cursor_timeout: self.__query_flags |= _QUERY_OPTIONS["no_timeout"] if allow_partial_results: self.__query_flags |= _QUERY_OPTIONS["partial"] if oplog_replay: self.__query_flags |= _QUERY_OPTIONS["oplog_replay"] # The namespace to use for find/getMore commands. self.__dbname = collection.database.name self.__collname = collection.name
def __init__(self, host=None, port=None, max_pool_size=10, network_timeout=None, document_class=dict, tz_aware=False, _connect=True, **kwargs): """Create a new connection to a single MongoDB instance at *host:port*. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`TypeError` if port is not an instance of ``int``. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `host` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. Any port specified in the host string(s) will override the `port` parameter. If multiple mongodb URIs containing database or auth information are passed, the last database, username, and password present will be used. For username and passwords reserved characters like ':', '/', '+' and '@' must be escaped following RFC 2396. :Parameters: - `host` (optional): hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `port` (optional): port number on which to connect - `max_pool_size` (optional): The maximum size limit for the connection pool. - `network_timeout` (optional): timeout (in seconds) to use for socket operations - default is no timeout - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`Connection` will be timezone aware (otherwise they will be naive) Other optional parameters can be passed as keyword arguments: - `safe`: Use getlasterror for each write operation? - `j` or `journal`: Block until write operations have been committed to the journal. Ignored if the server is running without journaling. Implies safe=True. - `w`: (integer or string) If this is a replica set write operations won't return until they have been replicated to the specified number or tagged set of servers. Implies safe=True. - `wtimeout`: Used in conjunction with `j` and/or `w`. Wait this many milliseconds for journal acknowledgement and/or write replication. Implies safe=True. - `fsync`: Force the database to fsync all files before returning When used with `j` the server awaits the next group commit before returning. Implies safe=True. - `replicaSet`: The name of the replica set to connect to. The driver will verify that the replica set it connects to matches this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. - `socketTimeoutMS`: How long a send or receive on a socket can take before timing out. - `connectTimeoutMS`: How long a connection can take to be opened before timing out. - `ssl`: If True, create the connection to the server using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.read_preferences.ReadPreference` for available options. - `auto_start_request`: If True (the default), each thread that accesses this Connection has a socket allocated to it for the thread's lifetime. This ensures consistent reads, even if you read after an unsafe write. - `use_greenlets` (optional): if ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` - `slave_okay` or `slaveOk` (deprecated): Use `read_preference` instead. .. seealso:: :meth:`end_request` .. versionchanged:: 2.3 Added support for failover between mongos seed list members. .. versionchanged:: 2.2 Added `auto_start_request` option back. Added `use_greenlets` option. .. versionchanged:: 2.1 Support `w` = integer or string. Added `ssl` option. DEPRECATED slave_okay/slaveOk. .. versionchanged:: 2.0 `slave_okay` is a pure keyword argument. Added support for safe, and getlasterror options as keyword arguments. .. versionchanged:: 1.11 Added `max_pool_size`. Completely removed previously deprecated `pool_size`, `auto_start_request` and `timeout` parameters. .. versionchanged:: 1.8 The `host` parameter can now be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. .. versionadded:: 1.8 The `tz_aware` parameter. .. versionadded:: 1.7 The `document_class` parameter. .. versionadded:: 1.1 The `network_timeout` parameter. .. mongodoc:: connections """ if host is None: host = self.HOST if isinstance(host, basestring): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") seeds = set() username = None password = None db = None options = {} for entity in host: if "://" in entity: if entity.startswith("mongodb://"): res = uri_parser.parse_uri(entity, port) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password db = res["database"] or db options = res["options"] else: idx = entity.find("://") raise InvalidURI("Invalid URI scheme: " "%s" % (entity[:idx], )) else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") self.__nodes = seeds self.__host = None self.__port = None self.__is_primary = False self.__is_mongos = False for option, value in kwargs.iteritems(): option, value = common.validate(option, value) options[option] = value self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__cursor_manager = CursorManager(self) self.__repl = options.get('replicaset') if len(seeds) == 1 and not self.__repl: self.__direct = True else: self.__direct = False self.__nodes = set() if network_timeout is not None: if (not isinstance(network_timeout, (int, float)) or network_timeout <= 0): raise ConfigurationError("network_timeout must " "be a positive integer") self.__net_timeout = (network_timeout or options.get('sockettimeoutms')) self.__conn_timeout = options.get('connecttimeoutms') self.__use_ssl = options.get('ssl', False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") if options.get('use_greenlets', False): if not pool.have_greenlet: raise ConfigurationError( "The greenlet module is not available. " "Install the greenlet package from PyPI.") self.pool_class = pool.GreenletPool else: self.pool_class = pool.Pool self.__pool = self.pool_class(None, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl) self.__document_class = document_class self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__auto_start_request = options.get('auto_start_request', True) # cache of existing indexes used by ensure_index ops self.__index_cache = {} self.__auth_credentials = {} super(Connection, self).__init__(**options) if self.slave_okay: warnings.warn( "slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) if _connect: self.__find_node(seeds) if db and username is None: warnings.warn("must provide a username and password " "to authenticate to %s" % (db, )) if username: db = db or "admin" if not self[db].authenticate(username, password): raise ConfigurationError("authentication failed")
def __init__(self, host=None, port=None, max_pool_size=10, document_class=dict, tz_aware=False, _connect=True, **kwargs): """Create a new connection to a single MongoDB instance at *host:port*. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`TypeError` if port is not an instance of ``int``. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `host` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. Any port specified in the host string(s) will override the `port` parameter. If multiple mongodb URIs containing database or auth information are passed, the last database, username, and password present will be used. For username and passwords reserved characters like ':', '/', '+' and '@' must be escaped following RFC 2396. :Parameters: - `host` (optional): hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `port` (optional): port number on which to connect - `max_pool_size` (optional): The maximum number of idle connections to keep open in the pool for future use - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MongoClient` will be timezone aware (otherwise they will be naive) **Other optional parameters can be passed as keyword arguments:** - `w`: (integer or string) If this is a replica set, write operations will block until they have been replicated to the specified number or tagged set of servers. `w=<int>` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). **Passing w=0 disables write acknowledgement and all other write concern options.** - `wtimeout`: (integer) Used in conjunction with `w`. Specify a value in milliseconds to control how long to wait for write propagation to complete. If replication does not complete in the given timeframe, a timeout exception is raised. - `j`: If ``True`` block until write operations have been committed to the journal. Ignored if the server is running without journaling. - `fsync`: If ``True`` force the database to fsync all files before returning. When used with `j` the server awaits the next group commit before returning. - `replicaSet`: (string) The name of the replica set to connect to. The driver will verify that the replica set it connects to matches this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. - `socketTimeoutMS`: (integer) How long (in milliseconds) a send or receive on a socket can take before timing out. - `connectTimeoutMS`: (integer) How long (in milliseconds) a connection can take to be opened before timing out. - `ssl`: If ``True``, create the connection to the server using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.read_preferences.ReadPreference` for available options. - `auto_start_request`: If ``True``, each thread that accesses this :class:`MongoClient` has a socket allocated to it for the thread's lifetime. This ensures consistent reads, even if you read after an unacknowledged write. Defaults to ``False`` - `use_greenlets`: If ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` .. seealso:: :meth:`end_request` .. mongodoc:: connections .. versionadded:: 2.4 """ if host is None: host = self.HOST if isinstance(host, basestring): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") seeds = set() username = None password = None db = None opts = {} for entity in host: if "://" in entity: if entity.startswith("mongodb://"): res = uri_parser.parse_uri(entity, port) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password db = res["database"] or db opts = res["options"] else: idx = entity.find("://") raise InvalidURI("Invalid URI scheme: " "%s" % (entity[:idx], )) else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") self.__nodes = seeds self.__host = None self.__port = None self.__is_primary = False self.__is_mongos = False options = {} for option, value in kwargs.iteritems(): option, value = common.validate(option, value) options[option] = value options.update(opts) self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__cursor_manager = CursorManager(self) self.__repl = options.get('replicaset') if len(seeds) == 1 and not self.__repl: self.__direct = True else: self.__direct = False self.__nodes = set() self.__net_timeout = options.get('sockettimeoutms') self.__conn_timeout = options.get('connecttimeoutms') self.__use_ssl = options.get('ssl', False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") if options.get('use_greenlets', False): if not pool.have_greenlet: raise ConfigurationError( "The greenlet module is not available. " "Install the greenlet package from PyPI.") self.pool_class = pool.GreenletPool else: self.pool_class = pool.Pool self.__pool = self.pool_class(None, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl) self.__document_class = document_class self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__auto_start_request = options.get('auto_start_request', False) # cache of existing indexes used by ensure_index ops self.__index_cache = {} self.__auth_credentials = {} super(MongoClient, self).__init__(**options) if self.slave_okay: warnings.warn( "slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) if _connect: try: self.__find_node(seeds) except AutoReconnect, e: # ConnectionFailure makes more sense here than AutoReconnect raise ConnectionFailure(str(e))
def __init__(self, collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, batch_size=0, manipulate=True, collation=None, hint=None, max_scan=None, max_time_ms=None, max=None, min=None, return_key=False, show_record_id=False, snapshot=False, comment=None, session=None): """Create a new cursor. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find` instead. .. mongodoc:: cursors """ # Initialize all attributes used in __del__ before possibly raising # an error to avoid attribute errors during garbage collection. self.__id = None self.__exhaust = False self.__exhaust_mgr = None self.__killed = False if session: self.__session = session self.__explicit_session = True else: self.__session = None self.__explicit_session = False spec = filter if spec is None: spec = {} validate_is_mapping("filter", spec) if not isinstance(skip, int): raise TypeError("skip must be an instance of int") if not isinstance(limit, int): raise TypeError("limit must be an instance of int") validate_boolean("no_cursor_timeout", no_cursor_timeout) if cursor_type not in (CursorType.NON_TAILABLE, CursorType.TAILABLE, CursorType.TAILABLE_AWAIT, CursorType.EXHAUST): raise ValueError("not a valid value for cursor_type") validate_boolean("allow_partial_results", allow_partial_results) validate_boolean("oplog_replay", oplog_replay) if modifiers is not None: warnings.warn("the 'modifiers' parameter is deprecated", DeprecationWarning, stacklevel=2) validate_is_mapping("modifiers", modifiers) if not isinstance(batch_size, integer_types): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") if projection is not None: if not projection: projection = {"_id": 1} projection = helpers._fields_list_to_dict(projection, "projection") self.__collection = collection self.__spec = spec self.__projection = projection self.__skip = skip self.__limit = limit self.__batch_size = batch_size self.__modifiers = modifiers and modifiers.copy() or {} self.__ordering = sort and helpers._index_document(sort) or None self.__max_scan = max_scan self.__explain = False self.__comment = comment self.__max_time_ms = max_time_ms self.__max_await_time_ms = None self.__max = max self.__min = min self.__manipulate = manipulate self.__collation = validate_collation_or_none(collation) self.__return_key = return_key self.__show_record_id = show_record_id self.__snapshot = snapshot self.__set_hint(hint) # Exhaust cursor support if cursor_type == CursorType.EXHAUST: if self.__collection.database.client.is_mongos: raise InvalidOperation('Exhaust cursors are ' 'not supported by mongos') if limit: raise InvalidOperation("Can't use limit and exhaust together.") self.__exhaust = True # This is ugly. People want to be able to do cursor[5:5] and # get an empty result set (old behavior was an # exception). It's hard to do that right, though, because the # server uses limit(0) to mean 'no limit'. So we set __empty # in that case and check for it when iterating. We also unset # it anytime we change __limit. self.__empty = False self.__data = deque() self.__address = None self.__retrieved = 0 self.__codec_options = collection.codec_options self.__read_preference = collection.read_preference self.__read_concern = collection.read_concern self.__query_flags = cursor_type if self.__read_preference != ReadPreference.PRIMARY: self.__query_flags |= _QUERY_OPTIONS["slave_okay"] if no_cursor_timeout: self.__query_flags |= _QUERY_OPTIONS["no_timeout"] if allow_partial_results: self.__query_flags |= _QUERY_OPTIONS["partial"] if oplog_replay: self.__query_flags |= _QUERY_OPTIONS["oplog_replay"]
def __init__( self, host=None, port=None, max_pool_size=10, document_class=dict, tz_aware=False, _connect=True, **kwargs ): """Create a new connection to a single MongoDB instance at *host:port*. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`TypeError` if port is not an instance of ``int``. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `host` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. Any port specified in the host string(s) will override the `port` parameter. If multiple mongodb URIs containing database or auth information are passed, the last database, username, and password present will be used. For username and passwords reserved characters like ':', '/', '+' and '@' must be escaped following RFC 2396. :Parameters: - `host` (optional): hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `port` (optional): port number on which to connect - `max_pool_size` (optional): The maximum number of idle connections to keep open in the pool for future use - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MongoClient` will be timezone aware (otherwise they will be naive) **Other optional parameters can be passed as keyword arguments:** - `w`: (integer or string) If this is a replica set, write operations will block until they have been replicated to the specified number or tagged set of servers. `w=<int>` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). **Passing w=0 disables write acknowledgement and all other write concern options.** - `wtimeout`: (integer) Used in conjunction with `w`. Specify a value in milliseconds to control how long to wait for write propagation to complete. If replication does not complete in the given timeframe, a timeout exception is raised. - `j`: If ``True`` block until write operations have been committed to the journal. Ignored if the server is running without journaling. - `fsync`: If ``True`` force the database to fsync all files before returning. When used with `j` the server awaits the next group commit before returning. - `replicaSet`: (string) The name of the replica set to connect to. The driver will verify that the replica set it connects to matches this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. - `socketTimeoutMS`: (integer) How long (in milliseconds) a send or receive on a socket can take before timing out. - `connectTimeoutMS`: (integer) How long (in milliseconds) a connection can take to be opened before timing out. - `ssl`: If ``True``, create the connection to the server using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.read_preferences.ReadPreference` for available options. - `auto_start_request`: If ``True``, each thread that accesses this :class:`MongoClient` has a socket allocated to it for the thread's lifetime. This ensures consistent reads, even if you read after an unacknowledged write. Defaults to ``False`` - `use_greenlets`: If ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` .. seealso:: :meth:`end_request` .. mongodoc:: connections .. versionadded:: 2.4 """ if host is None: host = self.HOST if isinstance(host, basestring): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") seeds = set() username = None password = None db = None opts = {} for entity in host: if "://" in entity: if entity.startswith("mongodb://"): res = uri_parser.parse_uri(entity, port) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password db = res["database"] or db opts = res["options"] else: idx = entity.find("://") raise InvalidURI("Invalid URI scheme: " "%s" % (entity[:idx],)) else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") self.__nodes = seeds self.__host = None self.__port = None self.__is_primary = False self.__is_mongos = False options = {} for option, value in kwargs.iteritems(): option, value = common.validate(option, value) options[option] = value options.update(opts) self.__max_pool_size = common.validate_positive_integer("max_pool_size", max_pool_size) self.__cursor_manager = CursorManager(self) self.__repl = options.get("replicaset") if len(seeds) == 1 and not self.__repl: self.__direct = True else: self.__direct = False self.__nodes = set() self.__net_timeout = options.get("sockettimeoutms") self.__conn_timeout = options.get("connecttimeoutms") self.__use_ssl = options.get("ssl", False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError( "The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI." ) use_greenlets = options.get("use_greenlets", False) self.__pool = pool.Pool( None, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl, use_greenlets ) self.__document_class = document_class self.__tz_aware = common.validate_boolean("tz_aware", tz_aware) self.__auto_start_request = options.get("auto_start_request", False) # cache of existing indexes used by ensure_index ops self.__index_cache = {} self.__auth_credentials = {} super(MongoClient, self).__init__(**options) if self.slave_okay: warnings.warn("slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) if _connect: try: self.__find_node(seeds) except AutoReconnect, e: # ConnectionFailure makes more sense here than AutoReconnect raise ConnectionFailure(str(e))
def __init__(self, host=None, port=None, max_pool_size=10, document_class=dict, tz_aware=False, _connect=True, **kwargs): """Create a new connection to a single MongoDB instance at *host:port*. The resultant client object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`TypeError` if port is not an instance of ``int``. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `host` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. Any port specified in the host string(s) will override the `port` parameter. If multiple mongodb URIs containing database or auth information are passed, the last database, username, and password present will be used. For username and passwords reserved characters like ':', '/', '+' and '@' must be escaped following RFC 2396. :Parameters: - `host` (optional): hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `port` (optional): port number on which to connect - `max_pool_size` (optional): The maximum number of idle connections to keep open in the pool for future use - `document_class` (optional): default class to use for documents returned from queries on this client - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`MongoClient` will be timezone aware (otherwise they will be naive) | **Other optional parameters can be passed as keyword arguments:** - `socketTimeoutMS`: (integer) How long (in milliseconds) a send or receive on a socket can take before timing out. - `connectTimeoutMS`: (integer) How long (in milliseconds) a connection can take to be opened before timing out. - `auto_start_request`: If ``True``, each thread that accesses this :class:`MongoClient` has a socket allocated to it for the thread's lifetime. This ensures consistent reads, even if you read after an unacknowledged write. Defaults to ``False`` - `use_greenlets`: If ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` | **Write Concern options:** - `w`: (integer or string) If this is a replica set, write operations will block until they have been replicated to the specified number or tagged set of servers. `w=<int>` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). Passing w=0 **disables write acknowledgement** and all other write concern options. - `wtimeout`: (integer) Used in conjunction with `w`. Specify a value in milliseconds to control how long to wait for write propagation to complete. If replication does not complete in the given timeframe, a timeout exception is raised. - `j`: If ``True`` block until write operations have been committed to the journal. Ignored if the server is running without journaling. - `fsync`: If ``True`` force the database to fsync all files before returning. When used with `j` the server awaits the next group commit before returning. | **Replica set keyword arguments for connecting with a replica set - either directly or via a mongos:** | (ignored by standalone mongod instances) - `replicaSet`: (string) The name of the replica set to connect to. The driver will verify that the replica set it connects to matches this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. *Ignored by mongos*. - `read_preference`: The read preference for this client. If connecting to a secondary then a read preference mode *other* than PRIMARY is required - otherwise all queries will throw :class:`~pymongo.errors.AutoReconnect` "not master". See :class:`~pymongo.read_preferences.ReadPreference` for all available read preference options. - `tag_sets`: Ignored unless connecting to a replica set via mongos. Specify a priority-order for tag sets, provide a list of tag sets: ``[{'dc': 'ny'}, {'dc': 'la'}, {}]``. A final, empty tag set, ``{}``, means "read from any member that matches the mode, ignoring tags. | **SSL configuration:** - `ssl`: If ``True``, create the connection to the server using SSL. - `ssl_keyfile`: The private keyfile used to identify the local connection against mongod. If included with the ``certfile` then only the ``ssl_certfile`` is needed. Implies ``ssl=True``. - `ssl_certfile`: The certificate file used to identify the local connection against mongod. Implies ``ssl=True``. - `ssl_cert_reqs`: Specifies whether a certificate is required from the other side of the connection, and whether it will be validated if provided. It must be one of the three values ``ssl.CERT_NONE`` (certificates ignored), ``ssl.CERT_OPTIONAL`` (not required, but validated if provided), or ``ssl.CERT_REQUIRED`` (required and validated). If the value of this parameter is not ``ssl.CERT_NONE``, then the ``ssl_ca_certs`` parameter must point to a file of CA certificates. Implies ``ssl=True``. - `ssl_ca_certs`: The ca_certs file contains a set of concatenated "certification authority" certificates, which are used to validate certificates passed from the other end of the connection. Implies ``ssl=True``. .. seealso:: :meth:`end_request` .. mongodoc:: connections .. versionchanged:: 2.5 Added addtional ssl options .. versionadded:: 2.4 """ if host is None: host = self.HOST if isinstance(host, basestring): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") seeds = set() username = None password = None db_name = None opts = {} for entity in host: if "://" in entity: if entity.startswith("mongodb://"): res = uri_parser.parse_uri(entity, port) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password db_name = res["database"] or db_name opts = res["options"] else: idx = entity.find("://") raise InvalidURI("Invalid URI scheme: " "%s" % (entity[:idx], )) else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") self.__nodes = seeds self.__host = None self.__port = None self.__is_primary = False self.__is_mongos = False # _pool_class option is for deep customization of PyMongo, e.g. Motor. # SHOULD NOT BE USED BY DEVELOPERS EXTERNAL TO 10GEN. pool_class = kwargs.pop('_pool_class', pool.Pool) options = {} for option, value in kwargs.iteritems(): option, value = common.validate(option, value) options[option] = value options.update(opts) self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__cursor_manager = CursorManager(self) self.__repl = options.get('replicaset') if len(seeds) == 1 and not self.__repl: self.__direct = True else: self.__direct = False self.__nodes = set() self.__net_timeout = options.get('sockettimeoutms') self.__conn_timeout = options.get('connecttimeoutms') self.__use_ssl = options.get('ssl', None) self.__ssl_keyfile = options.get('ssl_keyfile', None) self.__ssl_certfile = options.get('ssl_certfile', None) self.__ssl_cert_reqs = options.get('ssl_cert_reqs', None) self.__ssl_ca_certs = options.get('ssl_ca_certs', None) ssl_kwarg_keys = [k for k in kwargs.keys() if k.startswith('ssl_')] if self.__use_ssl == False and ssl_kwarg_keys: raise ConfigurationError("ssl has not been enabled but the " "following ssl parameters have been set: " "%s. Please set `ssl=True` or remove." % ', '.join(ssl_kwarg_keys)) if self.__ssl_cert_reqs and not self.__ssl_ca_certs: raise ConfigurationError("If `ssl_cert_reqs` is not " "`ssl.CERT_NONE` then you must " "include `ssl_ca_certs` to be able " "to validate the server.") if ssl_kwarg_keys and self.__use_ssl is None: # ssl options imply ssl = True self.__use_ssl = True if self.__use_ssl and not HAS_SSL: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") self.__use_greenlets = options.get('use_greenlets', False) self.__pool = pool_class(None, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl, use_greenlets=self.__use_greenlets, ssl_keyfile=self.__ssl_keyfile, ssl_certfile=self.__ssl_certfile, ssl_cert_reqs=self.__ssl_cert_reqs, ssl_ca_certs=self.__ssl_ca_certs) self.__document_class = document_class self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__auto_start_request = options.get('auto_start_request', False) # cache of existing indexes used by ensure_index ops self.__index_cache = {} self.__auth_credentials = {} super(MongoClient, self).__init__(**options) if self.slave_okay: warnings.warn( "slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning, stacklevel=2) if _connect: try: self.__find_node(seeds) except AutoReconnect, e: # ConnectionFailure makes more sense here than AutoReconnect raise ConnectionFailure(str(e))
def __init__(self, collection, filter=None, projection=None, skip=0, limit=0, no_cursor_timeout=False, cursor_type=CursorType.NON_TAILABLE, sort=None, allow_partial_results=False, oplog_replay=False, modifiers=None, batch_size=0, manipulate=True): """Create a new cursor. Should not be called directly by application developers - see :meth:`~pymongo.collection.Collection.find` instead. .. mongodoc:: cursors """ self.__id = None spec = filter if spec is None: spec = {} validate_is_mapping("filter", spec) if not isinstance(skip, int): raise TypeError("skip must be an instance of int") if not isinstance(limit, int): raise TypeError("limit must be an instance of int") validate_boolean("no_cursor_timeout", no_cursor_timeout) if cursor_type not in (CursorType.NON_TAILABLE, CursorType.TAILABLE, CursorType.TAILABLE_AWAIT, CursorType.EXHAUST): raise ValueError("not a valid value for cursor_type") validate_boolean("allow_partial_results", allow_partial_results) validate_boolean("oplog_replay", oplog_replay) if modifiers is not None: validate_is_mapping("modifiers", modifiers) if not isinstance(batch_size, integer_types): raise TypeError("batch_size must be an integer") if batch_size < 0: raise ValueError("batch_size must be >= 0") if projection is not None: if not projection: projection = {"_id": 1} projection = helpers._fields_list_to_dict(projection, "projection") self.__collection = collection self.__spec = spec self.__projection = projection self.__skip = skip self.__limit = limit self.__batch_size = batch_size self.__modifiers = modifiers and modifiers.copy() or {} self.__ordering = sort and helpers._index_document(sort) or None self.__max_scan = None self.__explain = False self.__hint = None self.__comment = None self.__max_time_ms = None self.__max_await_time_ms = None self.__max = None self.__min = None self.__manipulate = manipulate # Exhaust cursor support self.__exhaust = False self.__exhaust_mgr = None if cursor_type == CursorType.EXHAUST: if self.__collection.database.client.is_mongos: raise InvalidOperation('Exhaust cursors are ' 'not supported by mongos') if limit: raise InvalidOperation("Can't use limit and exhaust together.") self.__exhaust = True # This is ugly. People want to be able to do cursor[5:5] and # get an empty result set (old behavior was an # exception). It's hard to do that right, though, because the # server uses limit(0) to mean 'no limit'. So we set __empty # in that case and check for it when iterating. We also unset # it anytime we change __limit. self.__empty = False self.__data = deque() self.__address = None self.__retrieved = 0 self.__killed = False self.__codec_options = collection.codec_options self.__read_preference = collection.read_preference self.__read_concern = collection.read_concern self.__query_flags = cursor_type if self.__read_preference != ReadPreference.PRIMARY: self.__query_flags |= _QUERY_OPTIONS["slave_okay"] if no_cursor_timeout: self.__query_flags |= _QUERY_OPTIONS["no_timeout"] if allow_partial_results: self.__query_flags |= _QUERY_OPTIONS["partial"] if oplog_replay: self.__query_flags |= _QUERY_OPTIONS["oplog_replay"]
def __init__(self, host=None, port=None, max_pool_size=10, network_timeout=None, document_class=dict, tz_aware=False, _connect=True, **kwargs): """Create a new connection to a single MongoDB instance at *host:port*. The resultant connection object has connection-pooling built in. It also performs auto-reconnection when necessary. If an operation fails because of a connection error, :class:`~pymongo.errors.ConnectionFailure` is raised. If auto-reconnection will be performed, :class:`~pymongo.errors.AutoReconnect` will be raised. Application code should handle this exception (recognizing that the operation failed) and then continue to execute. Raises :class:`TypeError` if port is not an instance of ``int``. Raises :class:`~pymongo.errors.ConnectionFailure` if the connection cannot be made. The `host` parameter can be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. Any port specified in the host string(s) will override the `port` parameter. If multiple mongodb URIs containing database or auth information are passed, the last database, username, and password present will be used. For username and passwords reserved characters like ':', '/', '+' and '@' must be escaped following RFC 2396. :Parameters: - `host` (optional): hostname or IP address of the instance to connect to, or a mongodb URI, or a list of hostnames / mongodb URIs. If `host` is an IPv6 literal it must be enclosed in '[' and ']' characters following the RFC2732 URL syntax (e.g. '[::1]' for localhost) - `port` (optional): port number on which to connect - `max_pool_size` (optional): The maximum size limit for the connection pool. - `network_timeout` (optional): timeout (in seconds) to use for socket operations - default is no timeout - `document_class` (optional): default class to use for documents returned from queries on this connection - `tz_aware` (optional): if ``True``, :class:`~datetime.datetime` instances returned as values in a document by this :class:`Connection` will be timezone aware (otherwise they will be naive) Other optional parameters can be passed as keyword arguments: - `safe`: Use getlasterror for each write operation? - `j` or `journal`: Block until write operations have been committed to the journal. Ignored if the server is running without journaling. Implies safe=True. - `w`: (integer or string) If this is a replica set write operations won't return until they have been replicated to the specified number or tagged set of servers. `w` always includes the replica set primary (e.g. w=3 means write to the primary and wait until replicated to **two** secondaries). Implies safe=True. - `wtimeout`: Used in conjunction with `j` and/or `w`. Wait this many milliseconds for journal acknowledgement and/or write replication. Implies safe=True. - `fsync`: Force the database to fsync all files before returning When used with `j` the server awaits the next group commit before returning. Implies safe=True. - `replicaSet`: The name of the replica set to connect to. The driver will verify that the replica set it connects to matches this name. Implies that the hosts specified are a seed list and the driver should attempt to find all members of the set. - `socketTimeoutMS`: How long (in milliseconds) a send or receive on a socket can take before timing out. - `connectTimeoutMS`: How long (in milliseconds) a connection can take to be opened before timing out. - `ssl`: If True, create the connection to the server using SSL. - `read_preference`: The read preference for this connection. See :class:`~pymongo.read_preferences.ReadPreference` for available options. - `auto_start_request`: If True (the default), each thread that accesses this Connection has a socket allocated to it for the thread's lifetime. This ensures consistent reads, even if you read after an unsafe write. - `use_greenlets` (optional): if ``True``, :meth:`start_request()` will ensure that the current greenlet uses the same socket for all operations until :meth:`end_request()` - `slave_okay` or `slaveOk` (deprecated): Use `read_preference` instead. .. seealso:: :meth:`end_request` .. versionchanged:: 2.3 Added support for failover between mongos seed list members. .. versionchanged:: 2.2 Added `auto_start_request` option back. Added `use_greenlets` option. .. versionchanged:: 2.1 Support `w` = integer or string. Added `ssl` option. DEPRECATED slave_okay/slaveOk. .. versionchanged:: 2.0 `slave_okay` is a pure keyword argument. Added support for safe, and getlasterror options as keyword arguments. .. versionchanged:: 1.11 Added `max_pool_size`. Completely removed previously deprecated `pool_size`, `auto_start_request` and `timeout` parameters. .. versionchanged:: 1.8 The `host` parameter can now be a full `mongodb URI <http://dochub.mongodb.org/core/connections>`_, in addition to a simple hostname. It can also be a list of hostnames or URIs. .. versionadded:: 1.8 The `tz_aware` parameter. .. versionadded:: 1.7 The `document_class` parameter. .. versionadded:: 1.1 The `network_timeout` parameter. .. mongodoc:: connections """ if host is None: host = self.HOST if isinstance(host, basestring): host = [host] if port is None: port = self.PORT if not isinstance(port, int): raise TypeError("port must be an instance of int") seeds = set() username = None password = None db = None options = {} for entity in host: if "://" in entity: if entity.startswith("mongodb://"): res = uri_parser.parse_uri(entity, port) seeds.update(res["nodelist"]) username = res["username"] or username password = res["password"] or password db = res["database"] or db options = res["options"] else: idx = entity.find("://") raise InvalidURI("Invalid URI scheme: " "%s" % (entity[:idx],)) else: seeds.update(uri_parser.split_hosts(entity, port)) if not seeds: raise ConfigurationError("need to specify at least one host") self.__nodes = seeds self.__host = None self.__port = None self.__is_primary = False self.__is_mongos = False for option, value in kwargs.iteritems(): option, value = common.validate(option, value) options[option] = value self.__max_pool_size = common.validate_positive_integer( 'max_pool_size', max_pool_size) self.__cursor_manager = CursorManager(self) self.__repl = options.get('replicaset') if len(seeds) == 1 and not self.__repl: self.__direct = True else: self.__direct = False self.__nodes = set() if network_timeout is not None: if (not isinstance(network_timeout, (int, float)) or network_timeout <= 0): raise ConfigurationError("network_timeout must " "be a positive integer") self.__net_timeout = (network_timeout or options.get('sockettimeoutms')) self.__conn_timeout = options.get('connecttimeoutms') self.__use_ssl = options.get('ssl', False) if self.__use_ssl and not pool.have_ssl: raise ConfigurationError("The ssl module is not available. If you " "are using a python version previous to " "2.6 you must install the ssl package " "from PyPI.") if options.get('use_greenlets', False): if not pool.have_greenlet: raise ConfigurationError( "The greenlet module is not available. " "Install the greenlet package from PyPI." ) self.pool_class = pool.GreenletPool else: self.pool_class = pool.Pool self.__pool = self.pool_class( None, self.__max_pool_size, self.__net_timeout, self.__conn_timeout, self.__use_ssl ) self.__document_class = document_class self.__tz_aware = common.validate_boolean('tz_aware', tz_aware) self.__auto_start_request = options.get('auto_start_request', True) # cache of existing indexes used by ensure_index ops self.__index_cache = {} self.__auth_credentials = {} super(Connection, self).__init__(**options) if self.slave_okay: warnings.warn("slave_okay is deprecated. Please " "use read_preference instead.", DeprecationWarning) if _connect: try: self.__find_node(seeds) except AutoReconnect, e: # ConnectionFailure makes more sense here than AutoReconnect raise ConnectionFailure(str(e))