PYTHON-674 python 2/3 single-source for the pymongo module
This commit is contained in:
parent
f5c71a5376
commit
d494105aa4
@ -152,7 +152,8 @@ def _json_convert(obj):
|
||||
"""
|
||||
if hasattr(obj, 'iteritems') or hasattr(obj, 'items'): # PY3 support
|
||||
return SON(((k, _json_convert(v)) for k, v in iteritems(obj)))
|
||||
elif hasattr(obj, '__iter__') and not isinstance(obj, string_types):
|
||||
elif hasattr(obj, '__iter__') and not isinstance(obj, (text_type,
|
||||
binary_type)):
|
||||
return list((_json_convert(v) for v in obj))
|
||||
try:
|
||||
return default(obj)
|
||||
|
||||
@ -40,17 +40,26 @@ if PY3:
|
||||
return bytes.fromhex(h)
|
||||
|
||||
def iteritems(d):
|
||||
return d.items()
|
||||
return iter(d.items())
|
||||
|
||||
def itervalues(d):
|
||||
return iter(d.values())
|
||||
|
||||
def reraise(exctype, value, trace=None):
|
||||
raise exctype(str(value)).with_traceback(trace)
|
||||
|
||||
def _unicode(s):
|
||||
return s
|
||||
|
||||
binary_type = bytes
|
||||
text_type = str
|
||||
string_type = str
|
||||
integer_types = int
|
||||
next_item = "__next__"
|
||||
|
||||
# TODO: remove when gridfs module is made single-source
|
||||
next_item = '__next__'
|
||||
string_types = (bytes, text_type)
|
||||
else:
|
||||
try:
|
||||
from cStringIO import StringIO
|
||||
@ -73,15 +82,21 @@ else:
|
||||
def iteritems(d):
|
||||
return d.iteritems()
|
||||
|
||||
def itervalues(d):
|
||||
return d.itervalues()
|
||||
|
||||
# "raise x, y, z" raises SyntaxError in Python 3
|
||||
exec("""def reraise(exctype, value, trace=None):
|
||||
raise exctype, str(value), trace
|
||||
""")
|
||||
|
||||
_unicode = unicode
|
||||
|
||||
binary_type = str
|
||||
string_type = basestring
|
||||
text_type = unicode
|
||||
integer_types = (int, long)
|
||||
next_item = "next"
|
||||
|
||||
string_types = (binary_type, text_type)
|
||||
# TODO: remove when gridfs module is made single-source
|
||||
next_item = 'next'
|
||||
string_types = (bytes, text_type)
|
||||
|
||||
@ -14,7 +14,6 @@
|
||||
|
||||
"""Python driver for MongoDB."""
|
||||
|
||||
|
||||
ASCENDING = 1
|
||||
"""Ascending sort order."""
|
||||
DESCENDING = -1
|
||||
@ -70,7 +69,7 @@ ALL = 2
|
||||
version_tuple = (3, 0, ".dev0")
|
||||
|
||||
def get_version_string():
|
||||
if isinstance(version_tuple[-1], basestring):
|
||||
if isinstance(version_tuple[-1], str):
|
||||
return '.'.join(map(str, version_tuple[:-1])) + version_tuple[-1]
|
||||
return '.'.join(map(str, version_tuple))
|
||||
|
||||
|
||||
@ -14,15 +14,9 @@
|
||||
|
||||
"""Authentication helpers."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import hmac
|
||||
try:
|
||||
import hashlib
|
||||
_MD5 = hashlib.md5
|
||||
_DMOD = _MD5
|
||||
except ImportError: # for Python < 2.5
|
||||
import md5
|
||||
_MD5 = md5.new
|
||||
_DMOD = md5
|
||||
|
||||
HAVE_KERBEROS = True
|
||||
try:
|
||||
@ -30,8 +24,10 @@ try:
|
||||
except ImportError:
|
||||
HAVE_KERBEROS = False
|
||||
|
||||
from hashlib import md5
|
||||
|
||||
from bson.binary import Binary
|
||||
from bson.py3compat import b
|
||||
from bson.py3compat import b, string_type, _unicode
|
||||
from bson.son import SON
|
||||
from pymongo.errors import ConfigurationError, OperationFailure
|
||||
|
||||
@ -55,29 +51,29 @@ def _build_credentials_tuple(mech, source, user, passwd, extra):
|
||||
def _password_digest(username, password):
|
||||
"""Get a password digest to use for authentication.
|
||||
"""
|
||||
if not isinstance(password, basestring):
|
||||
raise TypeError("password must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
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 not isinstance(username, basestring):
|
||||
raise TypeError("username must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(username, string_type):
|
||||
raise TypeError("password must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
|
||||
md5hash = _MD5()
|
||||
md5hash = md5()
|
||||
data = "%s:mongo:%s" % (username, password)
|
||||
md5hash.update(data.encode('utf-8'))
|
||||
return unicode(md5hash.hexdigest())
|
||||
return _unicode(md5hash.hexdigest())
|
||||
|
||||
|
||||
def _auth_key(nonce, username, password):
|
||||
"""Get an auth key to use for authentication.
|
||||
"""
|
||||
digest = _password_digest(username, password)
|
||||
md5hash = _MD5()
|
||||
data = "%s%s%s" % (nonce, unicode(username), digest)
|
||||
md5hash = md5()
|
||||
data = "%s%s%s" % (nonce, _unicode(username), digest)
|
||||
md5hash.update(data.encode('utf-8'))
|
||||
return unicode(md5hash.hexdigest())
|
||||
return _unicode(md5hash.hexdigest())
|
||||
|
||||
|
||||
def _authenticate_gssapi(credentials, sock_info, cmd_func):
|
||||
@ -114,7 +110,7 @@ def _authenticate_gssapi(credentials, sock_info, cmd_func):
|
||||
response, _ = cmd_func(sock_info, '$external', cmd)
|
||||
|
||||
# Limit how many times we loop to catch protocol / library issues
|
||||
for _ in xrange(10):
|
||||
for _ in range(10):
|
||||
result = kerberos.authGSSClientStep(ctx,
|
||||
str(response['payload']))
|
||||
if result == -1:
|
||||
@ -156,7 +152,7 @@ def _authenticate_gssapi(credentials, sock_info, cmd_func):
|
||||
finally:
|
||||
kerberos.authGSSClientClean(ctx)
|
||||
|
||||
except kerberos.KrbError, exc:
|
||||
except kerberos.KrbError as exc:
|
||||
raise OperationFailure(str(exc))
|
||||
|
||||
|
||||
@ -181,14 +177,14 @@ def _authenticate_cram_md5(credentials, sock_info, cmd_func):
|
||||
passwd = _password_digest(username, password)
|
||||
cmd = SON([('saslStart', 1),
|
||||
('mechanism', 'CRAM-MD5'),
|
||||
('payload', Binary(b(''))),
|
||||
('payload', Binary(b'')),
|
||||
('autoAuthorize', 1)])
|
||||
response, _ = cmd_func(sock_info, source, cmd)
|
||||
# MD5 as implicit default digest for digestmod is deprecated
|
||||
# in python 3.4
|
||||
mac = hmac.HMAC(key=passwd.encode('utf-8'), digestmod=_DMOD)
|
||||
mac = hmac.HMAC(key=passwd.encode('utf-8'), digestmod=md5)
|
||||
mac.update(response['payload'])
|
||||
challenge = username.encode('utf-8') + b(' ') + b(mac.hexdigest())
|
||||
challenge = username.encode('utf-8') + b' ' + b(mac.hexdigest())
|
||||
cmd = SON([('saslContinue', 1),
|
||||
('conversationId', response['conversationId']),
|
||||
('payload', Binary(challenge))])
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
.. versionadded:: 2.7
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from bson.objectid import ObjectId
|
||||
from bson.son import SON
|
||||
from pymongo.errors import (BulkWriteError,
|
||||
@ -72,10 +74,10 @@ def _make_error(index, code, errmsg, operation):
|
||||
"""Create and return an error document.
|
||||
"""
|
||||
return {
|
||||
u"index": index,
|
||||
u"code": code,
|
||||
u"errmsg": errmsg,
|
||||
u"op": operation
|
||||
"index": index,
|
||||
"code": code,
|
||||
"errmsg": errmsg,
|
||||
"op": operation
|
||||
}
|
||||
|
||||
|
||||
@ -113,7 +115,7 @@ def _merge_legacy(run, full_result, result, index):
|
||||
full_result['nInserted'] += 1
|
||||
elif run.op_type == _UPDATE:
|
||||
if "upserted" in result:
|
||||
doc = {u"index": run.index(index), u"_id": result["upserted"]}
|
||||
doc = {"index": run.index(index), "_id": result["upserted"]}
|
||||
full_result["upserted"].append(doc)
|
||||
full_result['nUpserted'] += affected
|
||||
else:
|
||||
@ -146,7 +148,7 @@ def _merge_command(run, full_result, results):
|
||||
else:
|
||||
n_upserted = 1
|
||||
index = run.index(offset)
|
||||
doc = {u"index": index, u"_id": upserted}
|
||||
doc = {"index": index, "_id": upserted}
|
||||
full_result["upserted"].append(doc)
|
||||
full_result["nUpserted"] += n_upserted
|
||||
full_result["nMatched"] += (affected - n_upserted)
|
||||
@ -168,7 +170,7 @@ def _merge_command(run, full_result, results):
|
||||
idx = doc["index"] + offset
|
||||
doc["index"] = run.index(idx)
|
||||
# Add the failed operation to the error document.
|
||||
doc[u"op"] = run.ops[idx]
|
||||
doc["op"] = run.ops[idx]
|
||||
full_result["writeErrors"].extend(write_errors)
|
||||
|
||||
wc_error = result.get("writeConcernError")
|
||||
@ -207,7 +209,7 @@ class _Bulk(object):
|
||||
# Update can not be {}
|
||||
if not update:
|
||||
raise ValueError('update only works with $ operators')
|
||||
first = iter(update).next()
|
||||
first = next(iter(update))
|
||||
if not first.startswith('$'):
|
||||
raise ValueError('update only works with $ operators')
|
||||
cmd = SON([('q', selector), ('u', update),
|
||||
@ -221,7 +223,7 @@ class _Bulk(object):
|
||||
raise TypeError('replacement must be an instance of dict')
|
||||
# Replacement can be {}
|
||||
if replacement:
|
||||
first = iter(replacement).next()
|
||||
first = next(iter(replacement))
|
||||
if first.startswith('$'):
|
||||
raise ValueError('replacement can not include $ operators')
|
||||
cmd = SON([('q', selector), ('u', replacement),
|
||||
@ -378,7 +380,7 @@ class _Bulk(object):
|
||||
multi=(not operation['limit']),
|
||||
**write_concern)
|
||||
_merge_legacy(run, full_result, result, idx)
|
||||
except DocumentTooLarge, exc:
|
||||
except DocumentTooLarge as exc:
|
||||
# MongoDB 2.6 uses error code 2 for "too large".
|
||||
error = _make_error(
|
||||
run.index(idx), _BAD_VALUE, str(exc), operation)
|
||||
@ -386,7 +388,7 @@ class _Bulk(object):
|
||||
if self.ordered:
|
||||
stop = True
|
||||
break
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
if not exc.details:
|
||||
# Some error not related to the write operation
|
||||
# (e.g. kerberos failure). Re-raise immediately.
|
||||
|
||||
@ -14,10 +14,15 @@
|
||||
|
||||
"""Collection level utilities for Mongo."""
|
||||
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import warnings
|
||||
|
||||
from bson.code import Code
|
||||
from bson.objectid import ObjectId
|
||||
from bson.py3compat import (_unicode,
|
||||
integer_types,
|
||||
string_type)
|
||||
from bson.son import SON
|
||||
from pymongo import (bulk,
|
||||
common,
|
||||
@ -40,7 +45,7 @@ except ImportError:
|
||||
def _gen_index_name(keys):
|
||||
"""Generate an index name from the set of fields it is over.
|
||||
"""
|
||||
return u"_".join([u"%s_%s" % item for item in keys])
|
||||
return "_".join(["%s_%s" % item for item in keys])
|
||||
|
||||
|
||||
class Collection(common.BaseObject):
|
||||
@ -90,9 +95,9 @@ class Collection(common.BaseObject):
|
||||
uuidrepresentation=database.uuid_subtype,
|
||||
**database.write_concern)
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
"of %s" % (string_type.__name__,))
|
||||
|
||||
if not name or ".." in name:
|
||||
raise InvalidName("collection names cannot be empty")
|
||||
@ -108,8 +113,8 @@ class Collection(common.BaseObject):
|
||||
"null character")
|
||||
|
||||
self.__database = database
|
||||
self.__name = unicode(name)
|
||||
self.__full_name = u"%s.%s" % (self.__database.name, self.__name)
|
||||
self.__name = _unicode(name)
|
||||
self.__full_name = "%s.%s" % (self.__database.name, self.__name)
|
||||
if create or kwargs:
|
||||
self.__create(kwargs)
|
||||
|
||||
@ -132,7 +137,7 @@ class Collection(common.BaseObject):
|
||||
:Parameters:
|
||||
- `name`: the name of the collection to get
|
||||
"""
|
||||
return Collection(self.__database, u"%s.%s" % (self.__name, name))
|
||||
return Collection(self.__database, "%s.%s" % (self.__name, name))
|
||||
|
||||
def __getitem__(self, name):
|
||||
return self.__getattr__(name)
|
||||
@ -543,7 +548,7 @@ class Collection(common.BaseObject):
|
||||
# we check here. Passing a document with a mix of top level keys
|
||||
# starting with and without a '$' is invalid and the server will
|
||||
# raise an appropriate exception.
|
||||
first = (document.iterkeys()).next()
|
||||
first = next(iter(document))
|
||||
if first.startswith('$'):
|
||||
check_keys = False
|
||||
|
||||
@ -1018,7 +1023,8 @@ class Collection(common.BaseObject):
|
||||
DeprecationWarning, stacklevel=2)
|
||||
|
||||
# The types supported by datetime.timedelta. 2to3 removes long.
|
||||
if not isinstance(cache_for, (int, long, float)):
|
||||
if not (isinstance(cache_for, integer_types) or
|
||||
isinstance(cache_for, float)):
|
||||
raise TypeError("cache_for must be an integer or float.")
|
||||
|
||||
keys = helpers._index_list(key_or_list)
|
||||
@ -1037,7 +1043,7 @@ class Collection(common.BaseObject):
|
||||
|
||||
try:
|
||||
self.__database.command('createIndexes', self.name, indexes=[index])
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
if exc.code in (59, None):
|
||||
index["ns"] = self.__full_name
|
||||
self.__database.system.indexes.insert(index, manipulate=False,
|
||||
@ -1152,7 +1158,7 @@ class Collection(common.BaseObject):
|
||||
"""
|
||||
self.__database.connection._purge_index(self.__database.name,
|
||||
self.__name)
|
||||
self.drop_index(u"*")
|
||||
self.drop_index("*")
|
||||
|
||||
def drop_index(self, index_or_name):
|
||||
"""Drops the specified index on this collection.
|
||||
@ -1177,7 +1183,7 @@ class Collection(common.BaseObject):
|
||||
if isinstance(index_or_name, list):
|
||||
name = _gen_index_name(index_or_name)
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("index_or_name must be an index name or list")
|
||||
|
||||
self.__database.connection._purge_index(self.__database.name,
|
||||
@ -1357,7 +1363,7 @@ class Collection(common.BaseObject):
|
||||
"""
|
||||
|
||||
group = {}
|
||||
if isinstance(key, basestring):
|
||||
if isinstance(key, string_type):
|
||||
group["$keyf"] = Code(key)
|
||||
elif key is not None:
|
||||
group = {"key": helpers._fields_list_to_dict(key)}
|
||||
@ -1392,9 +1398,9 @@ class Collection(common.BaseObject):
|
||||
.. versionadded:: 1.7
|
||||
support for accepting keyword arguments for rename options
|
||||
"""
|
||||
if not isinstance(new_name, basestring):
|
||||
raise TypeError("new_name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(new_name, string_type):
|
||||
raise TypeError("new_name must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
|
||||
if not new_name or ".." in new_name:
|
||||
raise InvalidName("collection names cannot be empty")
|
||||
@ -1469,9 +1475,9 @@ class Collection(common.BaseObject):
|
||||
|
||||
.. mongodoc:: mapreduce
|
||||
"""
|
||||
if not isinstance(out, (basestring, dict)):
|
||||
if not isinstance(out, (string_type, dict)):
|
||||
raise TypeError("'out' must be an instance of "
|
||||
"%s or dict" % (basestring.__name__,))
|
||||
"%s or dict" % (string_type.__name__,))
|
||||
|
||||
mode = read_preference or self.read_preference
|
||||
response = self.__database.command("mapreduce", self.__name,
|
||||
@ -1642,6 +1648,8 @@ class Collection(common.BaseObject):
|
||||
def next(self):
|
||||
raise TypeError("'Collection' object is not iterable")
|
||||
|
||||
__next__ = next
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
"""This is only here so that some API misusages are easier to debug.
|
||||
"""
|
||||
|
||||
@ -16,6 +16,7 @@
|
||||
|
||||
from collections import deque
|
||||
|
||||
from bson.py3compat import integer_types
|
||||
from pymongo import helpers, message
|
||||
from pymongo.errors import AutoReconnect, CursorNotFound
|
||||
|
||||
@ -80,7 +81,7 @@ class CommandCursor(object):
|
||||
:Parameters:
|
||||
- `batch_size`: The size of each batch of results requested.
|
||||
"""
|
||||
if not isinstance(batch_size, (int, long)):
|
||||
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")
|
||||
@ -168,6 +169,8 @@ class CommandCursor(object):
|
||||
else:
|
||||
raise StopIteration
|
||||
|
||||
__next__ = next
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ from pymongo.errors import ConfigurationError
|
||||
from pymongo.write_concern import WriteConcern
|
||||
from bson.binary import (OLD_UUID_SUBTYPE, UUID_SUBTYPE,
|
||||
JAVA_LEGACY, CSHARP_LEGACY)
|
||||
from bson.py3compat import string_type, integer_types, iteritems
|
||||
|
||||
HAS_SSL = True
|
||||
try:
|
||||
@ -66,7 +67,7 @@ def validate_boolean(option, value):
|
||||
"""
|
||||
if isinstance(value, bool):
|
||||
return value
|
||||
elif isinstance(value, basestring):
|
||||
elif isinstance(value, string_type):
|
||||
if value not in ('true', 'false'):
|
||||
raise ConfigurationError("The value of %s must be "
|
||||
"'true' or 'false'" % (option,))
|
||||
@ -77,9 +78,9 @@ def validate_boolean(option, value):
|
||||
def validate_integer(option, value):
|
||||
"""Validates that 'value' is an integer (or basestring representation).
|
||||
"""
|
||||
if isinstance(value, (int, long)):
|
||||
if isinstance(value, integer_types):
|
||||
return value
|
||||
elif isinstance(value, basestring):
|
||||
elif isinstance(value, string_type):
|
||||
if not value.isdigit():
|
||||
raise ConfigurationError("The value of %s must be "
|
||||
"an integer" % (option,))
|
||||
@ -102,7 +103,7 @@ def validate_readable(option, value):
|
||||
"""
|
||||
# First make sure its a string py3.3 open(True, 'r') succeeds
|
||||
# Used in ssl cert checking due to poor ssl module error reporting
|
||||
value = validate_basestring(option, value)
|
||||
value = validate_string(option, value)
|
||||
open(value, 'r').close()
|
||||
return value
|
||||
|
||||
@ -132,21 +133,22 @@ def validate_positive_integer_or_none(option, value):
|
||||
return validate_positive_integer(option, value)
|
||||
|
||||
|
||||
def validate_basestring(option, value):
|
||||
"""Validates that 'value' is an instance of `basestring`.
|
||||
def validate_string(option, value):
|
||||
"""Validates that 'value' is an instance of `basestring` for Python 2
|
||||
or `str` for Python 3.
|
||||
"""
|
||||
if isinstance(value, basestring):
|
||||
if isinstance(value, string_type):
|
||||
return value
|
||||
raise TypeError("Wrong type for %s, value must be an "
|
||||
"instance of %s" % (option, basestring.__name__))
|
||||
raise TypeError("Wrong type for %s, value must be "
|
||||
"an instance of %s" % (option, string_type.__name__))
|
||||
|
||||
|
||||
def validate_int_or_basestring(option, value):
|
||||
"""Validates that 'value' is an integer or string.
|
||||
"""
|
||||
if isinstance(value, (int, long)):
|
||||
if isinstance(value, integer_types):
|
||||
return value
|
||||
elif isinstance(value, basestring):
|
||||
elif isinstance(value, string_type):
|
||||
if value.isdigit():
|
||||
return int(value)
|
||||
return value
|
||||
@ -214,10 +216,10 @@ def validate_auth_mechanism(option, value):
|
||||
def validate_uuid_representation(dummy, value):
|
||||
"""Validate the uuid representation option selected in the URI.
|
||||
"""
|
||||
if value not in _UUID_SUBTYPES.keys():
|
||||
if value not in _UUID_SUBTYPES:
|
||||
raise ConfigurationError("%s is an invalid UUID representation. "
|
||||
"Must be one of "
|
||||
"%s" % (value, _UUID_SUBTYPES.keys()))
|
||||
"%s" % (value, list(_UUID_SUBTYPES)))
|
||||
return _UUID_SUBTYPES[value]
|
||||
|
||||
|
||||
@ -249,7 +251,7 @@ def validate_read_preference_tags(name, value):
|
||||
# journal is an alias for j,
|
||||
# wtimeoutms is an alias for wtimeout,
|
||||
VALIDATORS = {
|
||||
'replicaset': validate_basestring,
|
||||
'replicaset': validate_string,
|
||||
'w': validate_int_or_basestring,
|
||||
'wtimeout': validate_integer,
|
||||
'wtimeoutms': validate_integer,
|
||||
@ -272,8 +274,8 @@ VALIDATORS = {
|
||||
'auto_start_request': validate_boolean,
|
||||
'use_greenlets': validate_boolean,
|
||||
'authmechanism': validate_auth_mechanism,
|
||||
'authsource': validate_basestring,
|
||||
'gssapiservicename': validate_basestring,
|
||||
'authsource': validate_string,
|
||||
'gssapiservicename': validate_string,
|
||||
'uuidrepresentation': validate_uuid_representation,
|
||||
}
|
||||
|
||||
@ -327,7 +329,7 @@ class BaseObject(object):
|
||||
def __set_options(self, options):
|
||||
"""Validates and sets all options passed to this object."""
|
||||
wc_opts = {}
|
||||
for option, value in options.iteritems():
|
||||
for option, value in iteritems(options):
|
||||
if option == 'read_preference':
|
||||
self.__read_pref = validate_read_preference(option, value)
|
||||
elif option == 'readpreference':
|
||||
|
||||
@ -18,6 +18,9 @@ from collections import deque
|
||||
|
||||
from bson import RE_TYPE
|
||||
from bson.code import Code
|
||||
from bson.py3compat import (iteritems,
|
||||
integer_types,
|
||||
string_type)
|
||||
from bson.son import SON
|
||||
from pymongo import helpers, message, read_preferences
|
||||
from pymongo.read_preferences import ReadPreference, SECONDARY_OK_COMMANDS
|
||||
@ -233,7 +236,7 @@ class Cursor(object):
|
||||
"batch_size", "max_scan", "as_class",
|
||||
"manipulate", "read_preference",
|
||||
"uuid_subtype", "compile_re", "query_flags")
|
||||
data = dict((k, v) for k, v in self.__dict__.iteritems()
|
||||
data = dict((k, v) for k, v in iteritems(self.__dict__)
|
||||
if k.startswith('_Cursor__') and k[9:] in values_to_clone)
|
||||
if deepcopy:
|
||||
data = self._deepcopy(data)
|
||||
@ -318,7 +321,7 @@ class Cursor(object):
|
||||
# by db.command or calling find_one on $cmd directly
|
||||
if self.collection.name == "$cmd":
|
||||
# Don't change commands that can't be sent to secondaries
|
||||
command_name = spec and spec.keys()[0].lower() or ""
|
||||
command_name = spec and next(iter(spec)).lower() or ""
|
||||
if command_name not in SECONDARY_OK_COMMANDS:
|
||||
return spec
|
||||
elif command_name == 'mapreduce':
|
||||
@ -345,7 +348,8 @@ class Cursor(object):
|
||||
# Checking spec.keys()[0] covers the case that the spec
|
||||
# was passed as an instance of SON or OrderedDict.
|
||||
elif ("query" in self.__spec and
|
||||
(len(self.__spec) == 1 or self.__spec.keys()[0] == "query")):
|
||||
(len(self.__spec) == 1 or
|
||||
next(iter(self.__spec)) == "query")):
|
||||
return SON({"$query": self.__spec})
|
||||
|
||||
return self.__spec
|
||||
@ -406,7 +410,7 @@ class Cursor(object):
|
||||
|
||||
.. mongodoc:: limit
|
||||
"""
|
||||
if not isinstance(limit, (int, long)):
|
||||
if not isinstance(limit, integer_types):
|
||||
raise TypeError("limit must be an integer")
|
||||
if self.__exhaust:
|
||||
raise InvalidOperation("Can't use limit and exhaust together.")
|
||||
@ -437,7 +441,7 @@ class Cursor(object):
|
||||
|
||||
.. versionadded:: 1.9
|
||||
"""
|
||||
if not isinstance(batch_size, (int, long)):
|
||||
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")
|
||||
@ -458,7 +462,7 @@ class Cursor(object):
|
||||
:Parameters:
|
||||
- `skip`: the number of results to skip
|
||||
"""
|
||||
if not isinstance(skip, (int, long)):
|
||||
if not isinstance(skip, integer_types):
|
||||
raise TypeError("skip must be an integer")
|
||||
if skip < 0:
|
||||
raise ValueError("skip must be >= 0")
|
||||
@ -480,7 +484,8 @@ class Cursor(object):
|
||||
:Parameters:
|
||||
- `max_time_ms`: the time limit after which the operation is aborted
|
||||
"""
|
||||
if not isinstance(max_time_ms, (int, long)) and max_time_ms is not None:
|
||||
if (not isinstance(max_time_ms, integer_types)
|
||||
and max_time_ms is not None):
|
||||
raise TypeError("max_time_ms must be an integer or None")
|
||||
self.__check_okay_to_chain()
|
||||
|
||||
@ -543,7 +548,7 @@ class Cursor(object):
|
||||
self.__limit = limit
|
||||
return self
|
||||
|
||||
if isinstance(index, (int, long)):
|
||||
if isinstance(index, integer_types):
|
||||
if index < 0:
|
||||
raise IndexError("Cursor instances do not support negative"
|
||||
"indices")
|
||||
@ -727,9 +732,9 @@ class Cursor(object):
|
||||
|
||||
.. versionadded:: 1.2
|
||||
"""
|
||||
if not isinstance(key, basestring):
|
||||
raise TypeError("key must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(key, string_type):
|
||||
raise TypeError("key must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
|
||||
options = {"key": key}
|
||||
if self.__spec:
|
||||
@ -758,7 +763,7 @@ class Cursor(object):
|
||||
# always use a hard limit for explains
|
||||
if c.__limit:
|
||||
c.__limit = -abs(c.__limit)
|
||||
return c.next()
|
||||
return next(c)
|
||||
|
||||
def hint(self, index):
|
||||
"""Adds a 'hint', telling Mongo the proper index to use for the query.
|
||||
@ -989,6 +994,8 @@ class Cursor(object):
|
||||
else:
|
||||
raise StopIteration
|
||||
|
||||
__next__ = next
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
@ -1018,7 +1025,7 @@ class Cursor(object):
|
||||
if not hasattr(x, 'items'):
|
||||
y, is_list, iterator = [], True, enumerate(x)
|
||||
else:
|
||||
y, is_list, iterator = {}, False, x.iteritems()
|
||||
y, is_list, iterator = {}, False, iteritems(x)
|
||||
|
||||
if memo is None:
|
||||
memo = {}
|
||||
|
||||
@ -24,6 +24,7 @@ installed on a connection by calling
|
||||
"""
|
||||
|
||||
import weakref
|
||||
from bson.py3compat import integer_types
|
||||
|
||||
|
||||
class CursorManager(object):
|
||||
@ -48,8 +49,8 @@ class CursorManager(object):
|
||||
:Parameters:
|
||||
- `cursor_id`: cursor id to close
|
||||
"""
|
||||
if not isinstance(cursor_id, (int, long)):
|
||||
raise TypeError("cursor_id must be an instance of (int, long)")
|
||||
if not isinstance(cursor_id, integer_types):
|
||||
raise TypeError("cursor_id must be an integer")
|
||||
|
||||
self.__connection().kill_cursors([cursor_id])
|
||||
|
||||
@ -83,8 +84,8 @@ class BatchCursorManager(CursorManager):
|
||||
:Parameters:
|
||||
- `cursor_id`: cursor id to close
|
||||
"""
|
||||
if not isinstance(cursor_id, (int, long)):
|
||||
raise TypeError("cursor_id must be an instance of (int, long)")
|
||||
if not isinstance(cursor_id, integer_types):
|
||||
raise TypeError("cursor_id must be an integer")
|
||||
|
||||
self.__dying_cursors.append(cursor_id)
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import warnings
|
||||
from bson.binary import OLD_UUID_SUBTYPE
|
||||
from bson.code import Code
|
||||
from bson.dbref import DBRef
|
||||
from bson.py3compat import iteritems, string_type, _unicode
|
||||
from bson.son import SON
|
||||
from pymongo import auth, common, helpers
|
||||
from pymongo.collection import Collection
|
||||
@ -65,14 +66,14 @@ class Database(common.BaseObject):
|
||||
uuidrepresentation=connection.uuid_subtype,
|
||||
**connection.write_concern)
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
"of %s" % (string_type.__name__,))
|
||||
|
||||
if name != '$external':
|
||||
_check_name(name)
|
||||
|
||||
self.__name = unicode(name)
|
||||
self.__name = _unicode(name)
|
||||
self.__connection = connection
|
||||
|
||||
self.__incoming_manipulators = []
|
||||
@ -274,11 +275,11 @@ class Database(common.BaseObject):
|
||||
"""Internal command helper.
|
||||
"""
|
||||
|
||||
if isinstance(command, basestring):
|
||||
if isinstance(command, string_type):
|
||||
command_name = command.lower()
|
||||
command = SON([(command, value)])
|
||||
else:
|
||||
command_name = command.keys()[0].lower()
|
||||
command_name = next(iter(command)).lower()
|
||||
|
||||
as_class = kwargs.pop('as_class', None)
|
||||
fields = kwargs.pop('fields', None)
|
||||
@ -435,13 +436,13 @@ class Database(common.BaseObject):
|
||||
if isinstance(name, Collection):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
raise TypeError("name_or_collection must be an instance of "
|
||||
"%s or Collection" % (basestring.__name__,))
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name_or_collection must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
|
||||
self.__connection._purge_index(self.__name, name)
|
||||
|
||||
self.command("drop", unicode(name), allowable_errors=["ns not found"])
|
||||
self.command("drop", _unicode(name), allowable_errors=["ns not found"])
|
||||
|
||||
def validate_collection(self, name_or_collection,
|
||||
scandata=False, full=False):
|
||||
@ -474,11 +475,11 @@ class Database(common.BaseObject):
|
||||
if isinstance(name, Collection):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name_or_collection must be an instance of "
|
||||
"%s or Collection" % (basestring.__name__,))
|
||||
"%s or Collection" % (string_type.__name__,))
|
||||
|
||||
result = self.command("validate", unicode(name),
|
||||
result = self.command("validate", _unicode(name),
|
||||
scandata=scandata, full=full)
|
||||
|
||||
valid = True
|
||||
@ -489,7 +490,7 @@ class Database(common.BaseObject):
|
||||
raise CollectionInvalid("%s invalid: %s" % (name, info))
|
||||
# Sharded results
|
||||
elif "raw" in result:
|
||||
for _, res in result["raw"].iteritems():
|
||||
for _, res in iteritems(result["raw"]):
|
||||
if "result" in res:
|
||||
info = res["result"]
|
||||
if (info.find("exception") != -1 or
|
||||
@ -626,6 +627,8 @@ class Database(common.BaseObject):
|
||||
def next(self):
|
||||
raise TypeError("'Database' object is not iterable")
|
||||
|
||||
__next__ = next
|
||||
|
||||
def _default_role(self, read_only):
|
||||
if self.name == "admin":
|
||||
if read_only:
|
||||
@ -686,7 +689,7 @@ class Database(common.BaseObject):
|
||||
|
||||
try:
|
||||
self.system.users.save(user, **self._get_wc_override())
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
# First admin user add fails gle in MongoDB >= 2.1.2
|
||||
# See SERVER-4225 for more information.
|
||||
if 'login' in str(exc):
|
||||
@ -722,13 +725,13 @@ class Database(common.BaseObject):
|
||||
|
||||
.. versionadded:: 1.4
|
||||
"""
|
||||
if not isinstance(name, basestring):
|
||||
raise TypeError("name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
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, basestring):
|
||||
raise TypeError("password must be an instance "
|
||||
"of %s or None" % (basestring.__name__,))
|
||||
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:
|
||||
@ -739,7 +742,7 @@ class Database(common.BaseObject):
|
||||
|
||||
try:
|
||||
uinfo = self.command("usersInfo", name)
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as 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
|
||||
@ -769,7 +772,7 @@ class Database(common.BaseObject):
|
||||
try:
|
||||
self.command("dropUser", name,
|
||||
writeConcern=self._get_wc_override())
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
# See comment in add_user try / except above.
|
||||
if exc.code in (59, None):
|
||||
self.system.users.remove({"user": name},
|
||||
@ -827,25 +830,25 @@ class Database(common.BaseObject):
|
||||
|
||||
.. mongodoc:: authenticate
|
||||
"""
|
||||
if not isinstance(name, basestring):
|
||||
raise TypeError("name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if password is not None and not isinstance(password, basestring):
|
||||
raise TypeError("password must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if source is not None and not isinstance(source, basestring):
|
||||
raise TypeError("source must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
if password is not None and not isinstance(password, string_type):
|
||||
raise TypeError("password must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
if source is not None and not isinstance(source, string_type):
|
||||
raise TypeError("source must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
common.validate_auth_mechanism('mechanism', mechanism)
|
||||
|
||||
validated_options = {}
|
||||
for option, value in kwargs.iteritems():
|
||||
for option, value in iteritems(kwargs):
|
||||
normalized, val = common.validate_auth_option(option, value)
|
||||
validated_options[normalized] = val
|
||||
|
||||
credentials = auth._build_credentials_tuple(mechanism,
|
||||
source or self.name, unicode(name),
|
||||
password and unicode(password) or None,
|
||||
source or self.name, _unicode(name),
|
||||
password and _unicode(password) or None,
|
||||
validated_options)
|
||||
self.connection._cache_credentials(self.name, credentials)
|
||||
return True
|
||||
|
||||
@ -21,6 +21,7 @@ import bson
|
||||
import pymongo
|
||||
|
||||
from bson.binary import OLD_UUID_SUBTYPE
|
||||
from bson.py3compat import itervalues, string_type
|
||||
from bson.son import SON
|
||||
from pymongo.errors import (AutoReconnect,
|
||||
CursorNotFound,
|
||||
@ -38,7 +39,7 @@ def _index_list(key_or_list, direction=None):
|
||||
if direction is not None:
|
||||
return [(key_or_list, direction)]
|
||||
else:
|
||||
if isinstance(key_or_list, basestring):
|
||||
if isinstance(key_or_list, string_type):
|
||||
return [(key_or_list, pymongo.ASCENDING)]
|
||||
elif not isinstance(key_or_list, (list, tuple)):
|
||||
raise TypeError("if no direction is specified, "
|
||||
@ -54,7 +55,7 @@ def _index_document(index_list):
|
||||
if isinstance(index_list, dict):
|
||||
raise TypeError("passing a dict to sort/create_index/hint is not "
|
||||
"allowed - use a list of tuples instead. did you "
|
||||
"mean %r?" % list(index_list.iteritems()))
|
||||
"mean %r?" % list(iteritems(index_list)))
|
||||
elif not isinstance(index_list, (list, tuple)):
|
||||
raise TypeError("must use a list of (key, direction) pairs, "
|
||||
"not: " + repr(index_list))
|
||||
@ -63,9 +64,9 @@ def _index_document(index_list):
|
||||
|
||||
index = SON()
|
||||
for (key, value) in index_list:
|
||||
if not isinstance(key, basestring):
|
||||
if not isinstance(key, string_type):
|
||||
raise TypeError("first item in each key pair must be a string")
|
||||
if not isinstance(value, (basestring, int, dict)):
|
||||
if not isinstance(value, (string_type, int, dict)):
|
||||
raise TypeError("second item in each key pair must be 1, -1, "
|
||||
"'2d', 'geoHaystack', or another valid MongoDB "
|
||||
"index specifier.")
|
||||
@ -142,7 +143,7 @@ def _check_command_response(response, reset, msg=None, allowable_errors=None):
|
||||
# Mongos returns the error details in a 'raw' object
|
||||
# for some errors.
|
||||
if "raw" in response:
|
||||
for shard in response["raw"].itervalues():
|
||||
for shard in itervalues(response["raw"]):
|
||||
if not shard.get("ok"):
|
||||
# Just grab the first error...
|
||||
details = shard
|
||||
@ -216,9 +217,9 @@ def _fields_list_to_dict(fields):
|
||||
"""
|
||||
as_dict = {}
|
||||
for field in fields:
|
||||
if not isinstance(field, basestring):
|
||||
if not isinstance(field, string_type):
|
||||
raise TypeError("fields must be a list of key names, "
|
||||
"each an instance of %s" % (basestring.__name__,))
|
||||
"each an instance of %s" % (string_type.__name__,))
|
||||
as_dict[field] = 1
|
||||
return as_dict
|
||||
|
||||
|
||||
@ -44,17 +44,17 @@ _INSERT = 0
|
||||
_UPDATE = 1
|
||||
_DELETE = 2
|
||||
|
||||
_EMPTY = b('')
|
||||
_BSONOBJ = b('\x03')
|
||||
_ZERO_8 = b('\x00')
|
||||
_ZERO_16 = b('\x00\x00')
|
||||
_ZERO_32 = b('\x00\x00\x00\x00')
|
||||
_ZERO_64 = b('\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
_SKIPLIM = b('\x00\x00\x00\x00\xff\xff\xff\xff')
|
||||
_EMPTY = b''
|
||||
_BSONOBJ = b'\x03'
|
||||
_ZERO_8 = b'\x00'
|
||||
_ZERO_16 = b'\x00\x00'
|
||||
_ZERO_32 = b'\x00\x00\x00\x00'
|
||||
_ZERO_64 = b'\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||
_SKIPLIM = b'\x00\x00\x00\x00\xff\xff\xff\xff'
|
||||
_OP_MAP = {
|
||||
_INSERT: b('\x04documents\x00\x00\x00\x00\x00'),
|
||||
_UPDATE: b('\x04updates\x00\x00\x00\x00\x00'),
|
||||
_DELETE: b('\x04deletes\x00\x00\x00\x00\x00'),
|
||||
_INSERT: b'\x04documents\x00\x00\x00\x00\x00',
|
||||
_UPDATE: b'\x04updates\x00\x00\x00\x00\x00',
|
||||
_DELETE: b'\x04deletes\x00\x00\x00\x00\x00',
|
||||
}
|
||||
|
||||
|
||||
@ -242,7 +242,7 @@ def _do_batched_insert(collection_name, docs, check_keys,
|
||||
send_safe), send_safe)
|
||||
# Exception type could be OperationFailure or a subtype
|
||||
# (e.g. DuplicateKeyError)
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
# Like it says, continue on error...
|
||||
if continue_on_error:
|
||||
# Store exception details to re-raise after the final batch.
|
||||
@ -294,7 +294,7 @@ def _do_batched_write_command(namespace, operation, command,
|
||||
# Save space for message length and request id
|
||||
buf.write(_ZERO_64)
|
||||
# responseTo, opCode
|
||||
buf.write(b("\x00\x00\x00\x00\xd4\x07\x00\x00"))
|
||||
buf.write(b"\x00\x00\x00\x00\xd4\x07\x00\x00")
|
||||
# No options
|
||||
buf.write(_ZERO_32)
|
||||
# Namespace as C string
|
||||
@ -380,7 +380,7 @@ def _do_batched_write_command(namespace, operation, command,
|
||||
buf.truncate()
|
||||
idx_offset += idx
|
||||
idx = 0
|
||||
key = b('0')
|
||||
key = b'0'
|
||||
buf.write(_BSONOBJ)
|
||||
buf.write(key)
|
||||
buf.write(_ZERO_8)
|
||||
|
||||
@ -40,7 +40,11 @@ import threading
|
||||
import time
|
||||
import warnings
|
||||
|
||||
from bson.py3compat import b
|
||||
from bson.py3compat import (_unicode,
|
||||
integer_types,
|
||||
iteritems,
|
||||
itervalues,
|
||||
string_type)
|
||||
from pymongo import (auth,
|
||||
common,
|
||||
database,
|
||||
@ -59,7 +63,7 @@ from pymongo.errors import (AutoReconnect,
|
||||
InvalidURI,
|
||||
OperationFailure)
|
||||
from pymongo.member import Member
|
||||
EMPTY = b("")
|
||||
EMPTY = b""
|
||||
|
||||
|
||||
def _partition_node(node):
|
||||
@ -227,7 +231,7 @@ class MongoClient(common.BaseObject):
|
||||
"""
|
||||
if host is None:
|
||||
host = self.HOST
|
||||
if isinstance(host, basestring):
|
||||
if isinstance(host, string_type):
|
||||
host = [host]
|
||||
if port is None:
|
||||
port = self.PORT
|
||||
@ -274,7 +278,7 @@ class MongoClient(common.BaseObject):
|
||||
event_class = kwargs.pop('_event_class', None)
|
||||
|
||||
options = {}
|
||||
for option, value in kwargs.iteritems():
|
||||
for option, value in iteritems(kwargs):
|
||||
option, value = common.validate(option, value)
|
||||
options[option] = value
|
||||
options.update(opts)
|
||||
@ -299,7 +303,7 @@ class MongoClient(common.BaseObject):
|
||||
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_')]
|
||||
ssl_kwarg_keys = [k for k in kwargs 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: "
|
||||
@ -355,7 +359,7 @@ class MongoClient(common.BaseObject):
|
||||
if _connect:
|
||||
try:
|
||||
self._ensure_connected(True)
|
||||
except AutoReconnect, e:
|
||||
except AutoReconnect as e:
|
||||
# ConnectionFailure makes more sense here than AutoReconnect
|
||||
raise ConnectionFailure(str(e))
|
||||
|
||||
@ -368,12 +372,12 @@ class MongoClient(common.BaseObject):
|
||||
|
||||
credentials = auth._build_credentials_tuple(mechanism,
|
||||
source,
|
||||
unicode(username),
|
||||
unicode(password),
|
||||
_unicode(username),
|
||||
_unicode(password),
|
||||
options)
|
||||
try:
|
||||
self._cache_credentials(source, credentials, _connect)
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
raise ConfigurationError(str(exc))
|
||||
|
||||
def _cached(self, dbname, coll, index):
|
||||
@ -479,7 +483,7 @@ class MongoClient(common.BaseObject):
|
||||
"""Authenticate using cached database credentials.
|
||||
"""
|
||||
if self.__auth_credentials or sock_info.authset:
|
||||
cached = set(self.__auth_credentials.itervalues())
|
||||
cached = set(itervalues(self.__auth_credentials))
|
||||
|
||||
authset = sock_info.authset.copy()
|
||||
|
||||
@ -806,7 +810,7 @@ class MongoClient(common.BaseObject):
|
||||
try:
|
||||
member, nodes = self.__find_node()
|
||||
return member
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
exc = e
|
||||
raise
|
||||
finally:
|
||||
@ -882,7 +886,7 @@ class MongoClient(common.BaseObject):
|
||||
# The server is available but something failed, e.g. auth,
|
||||
# wrong replica set name, or incompatible wire protocol.
|
||||
raise
|
||||
except Exception, why:
|
||||
except Exception as why:
|
||||
errors.append(str(why))
|
||||
|
||||
if len(mongos_candidates):
|
||||
@ -910,7 +914,7 @@ class MongoClient(common.BaseObject):
|
||||
connection_pool.start_request()
|
||||
|
||||
sock_info = connection_pool.get_socket()
|
||||
except socket.error, why:
|
||||
except socket.error as why:
|
||||
self.disconnect()
|
||||
|
||||
# Check if a unix domain socket
|
||||
@ -1130,7 +1134,7 @@ class MongoClient(common.BaseObject):
|
||||
return rv
|
||||
except OperationFailure:
|
||||
raise
|
||||
except (ConnectionFailure, socket.error), e:
|
||||
except (ConnectionFailure, socket.error) as e:
|
||||
self.disconnect()
|
||||
raise AutoReconnect(str(e))
|
||||
except:
|
||||
@ -1196,7 +1200,7 @@ class MongoClient(common.BaseObject):
|
||||
try:
|
||||
response = self.__send_and_receive(message, sock_info)
|
||||
return (None, (response, sock_info, member.pool))
|
||||
except (ConnectionFailure, socket.error), e:
|
||||
except (ConnectionFailure, socket.error) as e:
|
||||
self.disconnect()
|
||||
raise AutoReconnect(str(e))
|
||||
finally:
|
||||
@ -1315,7 +1319,7 @@ class MongoClient(common.BaseObject):
|
||||
:Parameters:
|
||||
- `cursor_id`: id of cursor to close
|
||||
"""
|
||||
if not isinstance(cursor_id, (int, long)):
|
||||
if not isinstance(cursor_id, integer_types):
|
||||
raise TypeError("cursor_id must be an instance of (int, long)")
|
||||
|
||||
self.__cursor_manager.close(cursor_id)
|
||||
@ -1360,9 +1364,9 @@ class MongoClient(common.BaseObject):
|
||||
if isinstance(name, database.Database):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
raise TypeError("name_or_database must be an instance of "
|
||||
"%s or Database" % (basestring.__name__,))
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name_or_database must be an instance "
|
||||
"of %s or a Database" % (string_type.__name__,))
|
||||
|
||||
self._purge_index(name)
|
||||
self[name].command("dropDatabase")
|
||||
@ -1394,12 +1398,12 @@ class MongoClient(common.BaseObject):
|
||||
|
||||
.. versionadded:: 1.5
|
||||
"""
|
||||
if not isinstance(from_name, basestring):
|
||||
raise TypeError("from_name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(to_name, basestring):
|
||||
raise TypeError("to_name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(from_name, string_type):
|
||||
raise TypeError("from_name must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
if not isinstance(to_name, string_type):
|
||||
raise TypeError("to_name must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
|
||||
database._check_name(to_name)
|
||||
|
||||
@ -1487,3 +1491,5 @@ class MongoClient(common.BaseObject):
|
||||
|
||||
def next(self):
|
||||
raise TypeError("'MongoClient' object is not iterable")
|
||||
|
||||
__next__ = next
|
||||
|
||||
@ -39,7 +39,11 @@ import threading
|
||||
import time
|
||||
import weakref
|
||||
|
||||
from bson.py3compat import b
|
||||
from bson.py3compat import (_unicode,
|
||||
integer_types,
|
||||
iteritems,
|
||||
itervalues,
|
||||
string_type)
|
||||
from pymongo import (auth,
|
||||
common,
|
||||
database,
|
||||
@ -60,7 +64,7 @@ from pymongo.errors import (AutoReconnect,
|
||||
InvalidOperation)
|
||||
from pymongo.thread_util import DummyLock
|
||||
|
||||
EMPTY = b("")
|
||||
EMPTY = b""
|
||||
MAX_RETRY = 3
|
||||
|
||||
MONITORS = set()
|
||||
@ -292,7 +296,8 @@ class RSState(object):
|
||||
|
||||
def __str__(self):
|
||||
return '<RSState [%s] writer="%s">' % (
|
||||
', '.join(str(member) for member in self._host_to_member.itervalues()),
|
||||
', '.join(str(member)
|
||||
for member in itervalues(self._host_to_member)),
|
||||
self.writer and '%s:%s' % self.writer or None)
|
||||
|
||||
|
||||
@ -610,7 +615,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
self.pool_class = kwargs.pop('_pool_class', pool.Pool)
|
||||
self.__monitor_class = kwargs.pop('_monitor_class', None)
|
||||
|
||||
for option, value in kwargs.iteritems():
|
||||
for option, value in iteritems(kwargs):
|
||||
option, value = common.validate(option, value)
|
||||
self.__opts[option] = value
|
||||
self.__opts.update(options)
|
||||
@ -645,7 +650,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
self.__ssl_cert_reqs = self.__opts.get('ssl_cert_reqs', None)
|
||||
self.__ssl_ca_certs = self.__opts.get('ssl_ca_certs', None)
|
||||
|
||||
ssl_kwarg_keys = [k for k in kwargs.keys() if k.startswith('ssl_')]
|
||||
ssl_kwarg_keys = [k for k in kwargs if k.startswith('ssl_')]
|
||||
if self.__use_ssl is False and ssl_kwarg_keys:
|
||||
raise ConfigurationError("ssl has not been enabled but the "
|
||||
"following ssl parameters have been set: "
|
||||
@ -673,7 +678,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
if _connect:
|
||||
try:
|
||||
self.refresh(initial=True)
|
||||
except AutoReconnect, e:
|
||||
except AutoReconnect as e:
|
||||
# ConnectionFailure makes more sense here than AutoReconnect
|
||||
raise ConnectionFailure(str(e))
|
||||
|
||||
@ -686,12 +691,12 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
|
||||
credentials = auth._build_credentials_tuple(mechanism,
|
||||
source,
|
||||
unicode(username),
|
||||
unicode(password),
|
||||
_unicode(username),
|
||||
_unicode(password),
|
||||
options)
|
||||
try:
|
||||
self._cache_credentials(source, credentials, _connect)
|
||||
except OperationFailure, exc:
|
||||
except OperationFailure as exc:
|
||||
raise ConfigurationError(str(exc))
|
||||
|
||||
# Start the monitor after we know the configuration is correct.
|
||||
@ -813,7 +818,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
"""Authenticate using cached database credentials.
|
||||
"""
|
||||
if self.__auth_credentials or sock_info.authset:
|
||||
cached = set(self.__auth_credentials.itervalues())
|
||||
cached = set(itervalues(self.__auth_credentials))
|
||||
|
||||
authset = sock_info.authset.copy()
|
||||
|
||||
@ -1104,7 +1109,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
rs_state = self.__rs_state
|
||||
try:
|
||||
self.__rs_state = self.__create_rs_state(rs_state, initial)
|
||||
except ConfigurationError, e:
|
||||
except ConfigurationError as e:
|
||||
self.__rs_state = rs_state.clone_with_error(e)
|
||||
raise
|
||||
|
||||
@ -1170,7 +1175,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
if response['ismaster']:
|
||||
writer = node
|
||||
|
||||
except (ConnectionFailure, socket.error), why:
|
||||
except (ConnectionFailure, socket.error) as why:
|
||||
if member:
|
||||
member.pool.discard_socket(sock_info)
|
||||
errors.append("%s:%d: %s" % (node[0], node[1], str(why)))
|
||||
@ -1242,7 +1247,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
if writer:
|
||||
response = members[writer].ismaster_response
|
||||
elif members:
|
||||
response = members.values()[0].ismaster_response
|
||||
response = next(itervalues(members)).ismaster_response
|
||||
else:
|
||||
response = {}
|
||||
|
||||
@ -1509,7 +1514,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
return rv
|
||||
except OperationFailure:
|
||||
raise
|
||||
except(ConnectionFailure, socket.error), why:
|
||||
except(ConnectionFailure, socket.error) as why:
|
||||
member.pool.discard_socket(sock_info)
|
||||
if _connection_to_use in (None, -1):
|
||||
self.disconnect()
|
||||
@ -1549,11 +1554,11 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
"""
|
||||
try:
|
||||
return self.__send_and_receive(member, msg, **kwargs)
|
||||
except socket.timeout, e:
|
||||
except socket.timeout as e:
|
||||
# Could be one slow query, don't refresh.
|
||||
host, port = member.host
|
||||
raise AutoReconnect("%s:%d: %s" % (host, port, e))
|
||||
except (socket.error, ConnectionFailure), why:
|
||||
except (socket.error, ConnectionFailure) as why:
|
||||
# Try to replace our RSState with a clone where this member is
|
||||
# marked "down", to reduce exceptions on other threads, or repeated
|
||||
# exceptions on this thread. We accept that there's a race
|
||||
@ -1629,7 +1634,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
return (
|
||||
pinned_member.host,
|
||||
self.__try_read(pinned_member, msg, **kwargs))
|
||||
except AutoReconnect, why:
|
||||
except AutoReconnect as why:
|
||||
if pref == ReadPreference.PRIMARY:
|
||||
self.disconnect()
|
||||
raise
|
||||
@ -1661,7 +1666,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
# unless read preference changes
|
||||
rs_state.pin_host(member.host, pref)
|
||||
return member.host, response
|
||||
except AutoReconnect, why:
|
||||
except AutoReconnect as why:
|
||||
if pref == ReadPreference.PRIMARY:
|
||||
raise
|
||||
|
||||
@ -1801,7 +1806,7 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
:Parameters:
|
||||
- `cursor_id`: id of cursor to close
|
||||
"""
|
||||
if not isinstance(cursor_id, (int, long)):
|
||||
if not isinstance(cursor_id, integer_types):
|
||||
raise TypeError("cursor_id must be an instance of (int, long)")
|
||||
|
||||
self._send_message(message.kill_cursors([cursor_id]),
|
||||
@ -1833,9 +1838,9 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
if isinstance(name, database.Database):
|
||||
name = name.name
|
||||
|
||||
if not isinstance(name, basestring):
|
||||
raise TypeError("name_or_database must be an instance of "
|
||||
"%s or Database" % (basestring.__name__,))
|
||||
if not isinstance(name, string_type):
|
||||
raise TypeError("name_or_database must be an instance "
|
||||
"of %s or a Database" % (string_type.__name__,))
|
||||
|
||||
self._purge_index(name)
|
||||
self[name].command("dropDatabase")
|
||||
@ -1865,12 +1870,12 @@ class MongoReplicaSetClient(common.BaseObject):
|
||||
.. note:: Specifying `username` and `password` requires server
|
||||
version **>= 1.3.3+**.
|
||||
"""
|
||||
if not isinstance(from_name, basestring):
|
||||
raise TypeError("from_name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(to_name, basestring):
|
||||
raise TypeError("to_name must be an instance "
|
||||
"of %s" % (basestring.__name__,))
|
||||
if not isinstance(from_name, string_type):
|
||||
raise TypeError("from_name must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
if not isinstance(to_name, string_type):
|
||||
raise TypeError("to_name must be an "
|
||||
"instance of %s" % (string_type.__name__,))
|
||||
|
||||
database._check_name(to_name)
|
||||
|
||||
|
||||
@ -221,7 +221,7 @@ class Pool:
|
||||
try:
|
||||
sock.connect(host)
|
||||
return sock
|
||||
except socket.error, e:
|
||||
except socket.error as e:
|
||||
if sock is not None:
|
||||
sock.close()
|
||||
raise e
|
||||
@ -243,7 +243,7 @@ class Pool:
|
||||
sock.settimeout(self.conn_timeout or 20.0)
|
||||
sock.connect(sa)
|
||||
return sock
|
||||
except socket.error, e:
|
||||
except socket.error as e:
|
||||
err = e
|
||||
if sock is not None:
|
||||
sock.close()
|
||||
|
||||
@ -15,7 +15,12 @@
|
||||
|
||||
"""Tools to parse and validate a MongoDB URI."""
|
||||
|
||||
from urllib import unquote_plus
|
||||
from bson.py3compat import PY3, iteritems, string_type
|
||||
|
||||
if PY3:
|
||||
from urllib.parse import unquote_plus
|
||||
else:
|
||||
from urllib import unquote_plus
|
||||
|
||||
from pymongo.common import validate
|
||||
from pymongo.errors import (ConfigurationError,
|
||||
@ -133,7 +138,7 @@ def parse_host(entity, default_port=DEFAULT_PORT):
|
||||
"address literal must be enclosed in '[' "
|
||||
"and ']' according to RFC 2732.")
|
||||
host, port = host.split(':', 1)
|
||||
if isinstance(port, basestring):
|
||||
if isinstance(port, string_type):
|
||||
if not port.isdigit():
|
||||
raise ConfigurationError("Port number must be an integer.")
|
||||
port = int(port)
|
||||
@ -149,7 +154,7 @@ def validate_options(opts):
|
||||
- `opts`: A dict of MongoDB URI options.
|
||||
"""
|
||||
normalized = {}
|
||||
for option, value in opts.iteritems():
|
||||
for option, value in iteritems(opts):
|
||||
option, value = validate(option, value)
|
||||
# str(option) to ensure that a unicode URI results in plain 'str'
|
||||
# option names. 'normalized' is then suitable to be passed as kwargs
|
||||
@ -322,6 +327,6 @@ if __name__ == '__main__':
|
||||
import sys
|
||||
try:
|
||||
pprint.pprint(parse_uri(sys.argv[1]))
|
||||
except (InvalidURI, UnsupportedOption), e:
|
||||
print e
|
||||
except (InvalidURI, UnsupportedOption) as e:
|
||||
print(e)
|
||||
sys.exit(0)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user