clean code related to Py2 + six.text_type & six.string_types

This commit is contained in:
Bastien Gérard 2020-03-11 21:50:50 +01:00
parent 421e3f324f
commit 03e34299f0
16 changed files with 101 additions and 148 deletions

View File

@ -28,7 +28,7 @@ Python3 codebase
Since 0.20, the codebase is exclusively Python 3. Since 0.20, the codebase is exclusively Python 3.
Earlier versions were exclusively Python2, and was relying on 2to3 to support Python3 installs. Earlier versions were exclusively Python2, and were relying on 2to3 to support Python3 installs.
Travis runs the tests against the main Python 3.x versions. Travis runs the tests against the main Python 3.x versions.

View File

@ -42,6 +42,8 @@ to both create the virtual environment and install the package. Otherwise, you c
download the source from `GitHub <http://github.com/MongoEngine/mongoengine>`_ and download the source from `GitHub <http://github.com/MongoEngine/mongoengine>`_ and
run ``python setup.py install``. run ``python setup.py install``.
The support for Python2 was dropped with MongoEngine 0.20.0
Dependencies Dependencies
============ ============
All of the dependencies can easily be installed via `pip <https://pip.pypa.io/>`_. All of the dependencies can easily be installed via `pip <https://pip.pypa.io/>`_.
@ -58,6 +60,10 @@ If you need to use an ``ImageField`` or ``ImageGridFsProxy``:
- Pillow>=2.0.0 - Pillow>=2.0.0
If you need to use signals:
- blinker>=1.3
Examples Examples
======== ========
Some simple examples of what MongoEngine code looks like: Some simple examples of what MongoEngine code looks like:

View File

@ -1,7 +1,6 @@
import weakref import weakref
from bson import DBRef from bson import DBRef
import six
from six import iteritems from six import iteritems
from mongoengine.common import _import_class from mongoengine.common import _import_class
@ -200,7 +199,7 @@ class EmbeddedDocumentList(BaseList):
""" """
for key, expected_value in kwargs.items(): for key, expected_value in kwargs.items():
doc_val = getattr(embedded_doc, key) doc_val = getattr(embedded_doc, key)
if doc_val != expected_value and six.text_type(doc_val) != expected_value: if doc_val != expected_value and str(doc_val) != expected_value:
return False return False
return True return True

View File

@ -294,7 +294,7 @@ class BaseDocument(object):
# TODO this could be simpler? # TODO this could be simpler?
if hasattr(self, "__unicode__"): if hasattr(self, "__unicode__"):
return self.__unicode__() return self.__unicode__()
return six.text_type("%s object" % self.__class__.__name__) return "%s object" % self.__class__.__name__
def __eq__(self, other): def __eq__(self, other):
if ( if (
@ -828,7 +828,7 @@ class BaseDocument(object):
@classmethod @classmethod
def _build_index_spec(cls, spec): def _build_index_spec(cls, spec):
"""Build a PyMongo index spec from a MongoEngine index spec.""" """Build a PyMongo index spec from a MongoEngine index spec."""
if isinstance(spec, six.string_types): if isinstance(spec, str):
spec = {"fields": [spec]} spec = {"fields": [spec]}
elif isinstance(spec, (list, tuple)): elif isinstance(spec, (list, tuple)):
spec = {"fields": list(spec)} spec = {"fields": list(spec)}
@ -925,7 +925,7 @@ class BaseDocument(object):
# Add any unique_with fields to the back of the index spec # Add any unique_with fields to the back of the index spec
if field.unique_with: if field.unique_with:
if isinstance(field.unique_with, six.string_types): if isinstance(field.unique_with, str):
field.unique_with = [field.unique_with] field.unique_with = [field.unique_with]
# Convert unique_with field names to real field names # Convert unique_with field names to real field names
@ -1172,9 +1172,6 @@ class BaseDocument(object):
else [value] else [value]
) )
return sep.join( return sep.join(
[ [str(dict(field.choices).get(val, val)) for val in values or []]
six.text_type(dict(field.choices).get(val, val))
for val in values or []
]
) )
return value return value

View File

@ -4,7 +4,6 @@ import weakref
from bson import DBRef, ObjectId, SON from bson import DBRef, ObjectId, SON
import pymongo import pymongo
import six
from six import iteritems from six import iteritems
from mongoengine.base.common import UPDATE_OPERATORS from mongoengine.base.common import UPDATE_OPERATORS
@ -92,13 +91,11 @@ class BaseField(object):
self._owner_document = None self._owner_document = None
# Make sure db_field is a string (if it's explicitly defined). # Make sure db_field is a string (if it's explicitly defined).
if self.db_field is not None and not isinstance( if self.db_field is not None and not isinstance(self.db_field, str):
self.db_field, six.string_types
):
raise TypeError("db_field should be a string.") raise TypeError("db_field should be a string.")
# Make sure db_field doesn't contain any forbidden characters. # Make sure db_field doesn't contain any forbidden characters.
if isinstance(self.db_field, six.string_types) and ( if isinstance(self.db_field, str) and (
"." in self.db_field "." in self.db_field
or "\0" in self.db_field or "\0" in self.db_field
or self.db_field.startswith("$") or self.db_field.startswith("$")
@ -221,14 +218,12 @@ class BaseField(object):
# Choices which are other types of Documents # Choices which are other types of Documents
if isinstance(value, (Document, EmbeddedDocument)): if isinstance(value, (Document, EmbeddedDocument)):
if not any(isinstance(value, c) for c in choice_list): if not any(isinstance(value, c) for c in choice_list):
self.error( self.error("Value must be an instance of %s" % (choice_list))
"Value must be an instance of %s" % (six.text_type(choice_list))
)
# Choices which are types other than Documents # Choices which are types other than Documents
else: else:
values = value if isinstance(value, (list, tuple)) else [value] values = value if isinstance(value, (list, tuple)) else [value]
if len(set(values) - set(choice_list)): if len(set(values) - set(choice_list)):
self.error("Value must be one of %s" % six.text_type(choice_list)) self.error("Value must be one of %s" % str(choice_list))
def _validate(self, value, **kwargs): def _validate(self, value, **kwargs):
# Check the Choices Constraint # Check the Choices Constraint
@ -345,7 +340,7 @@ class ComplexBaseField(BaseField):
def to_python(self, value): def to_python(self, value):
"""Convert a MongoDB-compatible type to a Python type.""" """Convert a MongoDB-compatible type to a Python type."""
if isinstance(value, six.string_types): if isinstance(value, str):
return value return value
if hasattr(value, "to_python"): if hasattr(value, "to_python"):
@ -399,7 +394,7 @@ class ComplexBaseField(BaseField):
EmbeddedDocument = _import_class("EmbeddedDocument") EmbeddedDocument = _import_class("EmbeddedDocument")
GenericReferenceField = _import_class("GenericReferenceField") GenericReferenceField = _import_class("GenericReferenceField")
if isinstance(value, six.string_types): if isinstance(value, str):
return value return value
if hasattr(value, "to_mongo"): if hasattr(value, "to_mongo"):
@ -513,10 +508,9 @@ class ObjectIdField(BaseField):
def to_mongo(self, value): def to_mongo(self, value):
if not isinstance(value, ObjectId): if not isinstance(value, ObjectId):
try: try:
return ObjectId(six.text_type(value)) return ObjectId(str(value))
except Exception as e: except Exception as e:
# e.message attribute has been deprecated since Python 2.6 self.error(str(e))
self.error(six.text_type(e))
return value return value
def prepare_query_value(self, op, value): def prepare_query_value(self, op, value):
@ -524,9 +518,9 @@ class ObjectIdField(BaseField):
def validate(self, value): def validate(self, value):
try: try:
ObjectId(six.text_type(value)) ObjectId(str(value))
except Exception: except Exception:
self.error("Invalid Object ID") self.error("Invalid ObjectID")
class GeoJsonBaseField(BaseField): class GeoJsonBaseField(BaseField):

View File

@ -1,7 +1,6 @@
import itertools import itertools
import warnings import warnings
import six
from six import iteritems, itervalues from six import iteritems, itervalues
from mongoengine.base.common import _document_registry from mongoengine.base.common import _document_registry
@ -180,14 +179,15 @@ class DocumentMetaclass(type):
# module continues to use im_func and im_self, so the code below # module continues to use im_func and im_self, so the code below
# copies __func__ into im_func and __self__ into im_self for # copies __func__ into im_func and __self__ into im_self for
# classmethod objects in Document derived classes. # classmethod objects in Document derived classes.
if six.PY3: #
for val in new_class.__dict__.values(): # Relates to https://github.com/MongoEngine/mongoengine/issues/1107
if isinstance(val, classmethod): # for val in new_class.__dict__.values():
f = val.__get__(new_class) # if isinstance(val, classmethod):
if hasattr(f, "__func__") and not hasattr(f, "im_func"): # f = val.__get__(new_class)
f.__dict__.update({"im_func": getattr(f, "__func__")}) # if hasattr(f, "__func__") and not hasattr(f, "im_func"):
if hasattr(f, "__self__") and not hasattr(f, "im_self"): # f.__dict__.update({"im_func": getattr(f, "__func__")})
f.__dict__.update({"im_self": getattr(f, "__self__")}) # if hasattr(f, "__self__") and not hasattr(f, "im_self"):
# f.__dict__.update({"im_self": getattr(f, "__self__")})
# Handle delete rules # Handle delete rules
for field in itervalues(new_class._fields): for field in itervalues(new_class._fields):

View File

@ -1,6 +1,5 @@
from pymongo import MongoClient, ReadPreference, uri_parser from pymongo import MongoClient, ReadPreference, uri_parser
from pymongo.database import _check_name from pymongo.database import _check_name
import six
__all__ = [ __all__ = [
"DEFAULT_CONNECTION_NAME", "DEFAULT_CONNECTION_NAME",
@ -39,8 +38,8 @@ def _check_db_name(name):
"""Check if a database name is valid. """Check if a database name is valid.
This functionality is copied from pymongo Database class constructor. This functionality is copied from pymongo Database class constructor.
""" """
if not isinstance(name, six.string_types): if not isinstance(name, str):
raise TypeError("name must be an instance of %s" % six.string_types) raise TypeError("name must be an instance of %s" % str)
elif name != "$external": elif name != "$external":
_check_name(name) _check_name(name)
@ -93,7 +92,7 @@ def _get_connection_settings(
conn_host = conn_settings["host"] conn_host = conn_settings["host"]
# Host can be a list or a string, so if string, force to a list. # Host can be a list or a string, so if string, force to a list.
if isinstance(conn_host, six.string_types): if isinstance(conn_host, str):
conn_host = [conn_host] conn_host = [conn_host]
resolved_hosts = [] resolved_hosts = []
@ -148,7 +147,7 @@ def _get_connection_settings(
# TODO simplify the code below once we drop support for # TODO simplify the code below once we drop support for
# PyMongo v3.4. # PyMongo v3.4.
read_pf_mode = uri_options["readpreference"] read_pf_mode = uri_options["readpreference"]
if isinstance(read_pf_mode, six.string_types): if isinstance(read_pf_mode, str):
read_pf_mode = read_pf_mode.lower() read_pf_mode = read_pf_mode.lower()
for preference in read_preferences: for preference in read_preferences:
if ( if (

View File

@ -30,7 +30,7 @@ class DeReference(object):
:class:`~mongoengine.base.ComplexBaseField` :class:`~mongoengine.base.ComplexBaseField`
:param get: A boolean determining if being called by __get__ :param get: A boolean determining if being called by __get__
""" """
if items is None or isinstance(items, six.string_types): if items is None or isinstance(items, str):
return items return items
# cheapest way to convert a queryset to a list # cheapest way to convert a queryset to a list
@ -274,9 +274,7 @@ class DeReference(object):
(v["_ref"].collection, v["_ref"].id), v (v["_ref"].collection, v["_ref"].id), v
) )
elif isinstance(v, (dict, list, tuple)) and depth <= self.max_depth: elif isinstance(v, (dict, list, tuple)) and depth <= self.max_depth:
item_name = six.text_type("{0}.{1}.{2}").format( item_name = "{0}.{1}.{2}".format(name, k, field_name)
name, k, field_name
)
data[k]._data[field_name] = self._attach_objects( data[k]._data[field_name] = self._attach_objects(
v, depth, instance=instance, name=item_name v, depth, instance=instance, name=item_name
) )

View File

@ -44,7 +44,7 @@ def includes_cls(fields):
"""Helper function used for ensuring and comparing indexes.""" """Helper function used for ensuring and comparing indexes."""
first_field = None first_field = None
if len(fields): if len(fields):
if isinstance(fields[0], six.string_types): if isinstance(fields[0], str):
first_field = fields[0] first_field = fields[0]
elif isinstance(fields[0], (list, tuple)) and len(fields[0]): elif isinstance(fields[0], (list, tuple)) and len(fields[0]):
first_field = fields[0][0] first_field = fields[0][0]
@ -430,15 +430,15 @@ class Document(six.with_metaclass(TopLevelDocumentMetaclass, BaseDocument)):
except pymongo.errors.DuplicateKeyError as err: except pymongo.errors.DuplicateKeyError as err:
message = u"Tried to save duplicate unique keys (%s)" message = u"Tried to save duplicate unique keys (%s)"
raise NotUniqueError(message % six.text_type(err)) raise NotUniqueError(message % err)
except pymongo.errors.OperationFailure as err: except pymongo.errors.OperationFailure as err:
message = "Could not save document (%s)" message = "Could not save document (%s)"
if re.match("^E1100[01] duplicate key", six.text_type(err)): if re.match("^E1100[01] duplicate key", str(err)):
# E11000 - duplicate key error index # E11000 - duplicate key error index
# E11001 - duplicate key on update # E11001 - duplicate key on update
message = u"Tried to save duplicate unique keys (%s)" message = u"Tried to save duplicate unique keys (%s)"
raise NotUniqueError(message % six.text_type(err)) raise NotUniqueError(message % err)
raise OperationError(message % six.text_type(err)) raise OperationError(message % err)
# Make sure we store the PK on this document now that it's saved # Make sure we store the PK on this document now that it's saved
id_field = self._meta["id_field"] id_field = self._meta["id_field"]

View File

@ -1,6 +1,5 @@
from collections import defaultdict from collections import defaultdict
import six
from six import iteritems from six import iteritems
__all__ = ( __all__ = (
@ -93,7 +92,7 @@ class ValidationError(AssertionError):
self.message = message self.message = message
def __str__(self): def __str__(self):
return six.text_type(self.message) return str(self.message)
def __repr__(self): def __repr__(self):
return "%s(%s,)" % (self.__class__.__name__, self.message) return "%s(%s,)" % (self.__class__.__name__, self.message)
@ -131,7 +130,7 @@ class ValidationError(AssertionError):
elif isinstance(source, ValidationError) and source.errors: elif isinstance(source, ValidationError) and source.errors:
return build_dict(source.errors) return build_dict(source.errors)
else: else:
return six.text_type(source) return str(source)
return errors_dict return errors_dict

View File

@ -108,7 +108,7 @@ class StringField(BaseField):
super(StringField, self).__init__(**kwargs) super(StringField, self).__init__(**kwargs)
def to_python(self, value): def to_python(self, value):
if isinstance(value, six.text_type): if isinstance(value, str):
return value return value
try: try:
value = value.decode("utf-8") value = value.decode("utf-8")
@ -117,7 +117,7 @@ class StringField(BaseField):
return value return value
def validate(self, value): def validate(self, value):
if not isinstance(value, six.string_types): if not isinstance(value, str):
self.error("StringField only accepts string values") self.error("StringField only accepts string values")
if self.max_length is not None and len(value) > self.max_length: if self.max_length is not None and len(value) > self.max_length:
@ -133,7 +133,7 @@ class StringField(BaseField):
return None return None
def prepare_query_value(self, op, value): def prepare_query_value(self, op, value):
if not isinstance(op, six.string_types): if not isinstance(op, str):
return value return value
if op in STRING_OPERATORS: if op in STRING_OPERATORS:
@ -472,13 +472,13 @@ class DecimalField(BaseField):
if value is None: if value is None:
return value return value
if self.force_string: if self.force_string:
return six.text_type(self.to_python(value)) return str(self.to_python(value))
return float(self.to_python(value)) return float(self.to_python(value))
def validate(self, value): def validate(self, value):
if not isinstance(value, decimal.Decimal): if not isinstance(value, decimal.Decimal):
if not isinstance(value, six.string_types): if not isinstance(value, str):
value = six.text_type(value) value = str(value)
try: try:
value = decimal.Decimal(value) value = decimal.Decimal(value)
except (TypeError, ValueError, decimal.InvalidOperation) as exc: except (TypeError, ValueError, decimal.InvalidOperation) as exc:
@ -543,7 +543,7 @@ class DateTimeField(BaseField):
if callable(value): if callable(value):
return value() return value()
if not isinstance(value, six.string_types): if not isinstance(value, str):
return None return None
return self._parse_datetime(value) return self._parse_datetime(value)
@ -707,7 +707,7 @@ class EmbeddedDocumentField(BaseField):
def __init__(self, document_type, **kwargs): def __init__(self, document_type, **kwargs):
# XXX ValidationError raised outside of the "validate" method. # XXX ValidationError raised outside of the "validate" method.
if not ( if not (
isinstance(document_type, six.string_types) isinstance(document_type, str)
or issubclass(document_type, EmbeddedDocument) or issubclass(document_type, EmbeddedDocument)
): ):
self.error( self.error(
@ -720,7 +720,7 @@ class EmbeddedDocumentField(BaseField):
@property @property
def document_type(self): def document_type(self):
if isinstance(self.document_type_obj, six.string_types): if isinstance(self.document_type_obj, str):
if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT:
resolved_document_type = self.owner_document resolved_document_type = self.owner_document
else: else:
@ -846,7 +846,7 @@ class DynamicField(BaseField):
"""Convert a Python type to a MongoDB compatible type. """Convert a Python type to a MongoDB compatible type.
""" """
if isinstance(value, six.string_types): if isinstance(value, str):
return value return value
if hasattr(value, "to_mongo"): if hasattr(value, "to_mongo"):
@ -889,7 +889,7 @@ class DynamicField(BaseField):
return member_name return member_name
def prepare_query_value(self, op, value): def prepare_query_value(self, op, value):
if isinstance(value, six.string_types): if isinstance(value, str):
return StringField().prepare_query_value(op, value) return StringField().prepare_query_value(op, value)
return super(DynamicField, self).prepare_query_value(op, self.to_mongo(value)) return super(DynamicField, self).prepare_query_value(op, self.to_mongo(value))
@ -954,7 +954,7 @@ class ListField(ComplexBaseField):
if ( if (
op in ("set", "unset", None) op in ("set", "unset", None)
and hasattr(value, "__iter__") and hasattr(value, "__iter__")
and not isinstance(value, six.string_types) and not isinstance(value, str)
and not isinstance(value, BaseDocument) and not isinstance(value, BaseDocument)
): ):
return [self.field.prepare_query_value(op, v) for v in value] return [self.field.prepare_query_value(op, v) for v in value]
@ -1026,9 +1026,7 @@ def key_not_string(d):
dictionary is not a string. dictionary is not a string.
""" """
for k, v in d.items(): for k, v in d.items():
if not isinstance(k, six.string_types) or ( if not isinstance(k, str) or (isinstance(v, dict) and key_not_string(v)):
isinstance(v, dict) and key_not_string(v)
):
return True return True
@ -1107,7 +1105,7 @@ class DictField(ComplexBaseField):
"iexact", "iexact",
] ]
if op in match_operators and isinstance(value, six.string_types): if op in match_operators and isinstance(value, str):
return StringField().prepare_query_value(op, value) return StringField().prepare_query_value(op, value)
if hasattr( if hasattr(
@ -1194,7 +1192,7 @@ class ReferenceField(BaseField):
:class:`~pymongo.dbref.DBRef`, regardless of the value of `dbref`. :class:`~pymongo.dbref.DBRef`, regardless of the value of `dbref`.
""" """
# XXX ValidationError raised outside of the "validate" method. # XXX ValidationError raised outside of the "validate" method.
if not isinstance(document_type, six.string_types) and not issubclass( if not isinstance(document_type, str) and not issubclass(
document_type, Document document_type, Document
): ):
self.error( self.error(
@ -1209,7 +1207,7 @@ class ReferenceField(BaseField):
@property @property
def document_type(self): def document_type(self):
if isinstance(self.document_type_obj, six.string_types): if isinstance(self.document_type_obj, str):
if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT:
self.document_type_obj = self.owner_document self.document_type_obj = self.owner_document
else: else:
@ -1325,7 +1323,7 @@ class CachedReferenceField(BaseField):
fields = [] fields = []
# XXX ValidationError raised outside of the "validate" method. # XXX ValidationError raised outside of the "validate" method.
if not isinstance(document_type, six.string_types) and not issubclass( if not isinstance(document_type, str) and not issubclass(
document_type, Document document_type, Document
): ):
self.error( self.error(
@ -1370,7 +1368,7 @@ class CachedReferenceField(BaseField):
@property @property
def document_type(self): def document_type(self):
if isinstance(self.document_type_obj, six.string_types): if isinstance(self.document_type_obj, str):
if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT:
self.document_type_obj = self.owner_document self.document_type_obj = self.owner_document
else: else:
@ -1498,7 +1496,7 @@ class GenericReferenceField(BaseField):
# Keep the choices as a list of allowed Document class names # Keep the choices as a list of allowed Document class names
if choices: if choices:
for choice in choices: for choice in choices:
if isinstance(choice, six.string_types): if isinstance(choice, str):
self.choices.append(choice) self.choices.append(choice)
elif isinstance(choice, type) and issubclass(choice, Document): elif isinstance(choice, type) and issubclass(choice, Document):
self.choices.append(choice._class_name) self.choices.append(choice._class_name)
@ -1507,7 +1505,7 @@ class GenericReferenceField(BaseField):
# method. # method.
self.error( self.error(
"Invalid choices provided: must be a list of" "Invalid choices provided: must be a list of"
"Document subclasses and/or six.string_typess" "Document subclasses and/or str"
) )
def _validate_choices(self, value): def _validate_choices(self, value):
@ -1601,8 +1599,8 @@ class BinaryField(BaseField):
def __set__(self, instance, value): def __set__(self, instance, value):
"""Handle bytearrays in python 3.1""" """Handle bytearrays in python 3.1"""
if six.PY3 and isinstance(value, bytearray): if isinstance(value, bytearray):
value = six.binary_type(value) value = bytes(value)
return super(BinaryField, self).__set__(instance, value) return super(BinaryField, self).__set__(instance, value)
def to_mongo(self, value): def to_mongo(self, value):
@ -1831,7 +1829,7 @@ class FileField(BaseField):
key = self.name key = self.name
if ( if (
hasattr(value, "read") and not isinstance(value, GridFSProxy) hasattr(value, "read") and not isinstance(value, GridFSProxy)
) or isinstance(value, (six.binary_type, six.string_types)): ) or isinstance(value, (six.binary_type, str)):
# using "FileField() = file/string" notation # using "FileField() = file/string" notation
grid_file = instance._data.get(self.name) grid_file = instance._data.get(self.name)
# If a file already exists, delete it # If a file already exists, delete it
@ -2038,12 +2036,7 @@ class ImageField(FileField):
for att_name, att in extra_args.items(): for att_name, att in extra_args.items():
value = None value = None
if isinstance(att, (tuple, list)): if isinstance(att, (tuple, list)):
if six.PY3: value = dict(itertools.zip_longest(params_size, att, fillvalue=None))
value = dict(
itertools.zip_longest(params_size, att, fillvalue=None)
)
else:
value = dict(map(None, params_size, att))
setattr(self, att_name, value) setattr(self, att_name, value)
@ -2213,8 +2206,8 @@ class UUIDField(BaseField):
if not self._binary: if not self._binary:
original_value = value original_value = value
try: try:
if not isinstance(value, six.string_types): if not isinstance(value, str):
value = six.text_type(value) value = str(value)
return uuid.UUID(value) return uuid.UUID(value)
except (ValueError, TypeError, AttributeError): except (ValueError, TypeError, AttributeError):
return original_value return original_value
@ -2222,8 +2215,8 @@ class UUIDField(BaseField):
def to_mongo(self, value): def to_mongo(self, value):
if not self._binary: if not self._binary:
return six.text_type(value) return str(value)
elif isinstance(value, six.string_types): elif isinstance(value, str):
return uuid.UUID(value) return uuid.UUID(value)
return value return value
@ -2234,7 +2227,7 @@ class UUIDField(BaseField):
def validate(self, value): def validate(self, value):
if not isinstance(value, uuid.UUID): if not isinstance(value, uuid.UUID):
if not isinstance(value, six.string_types): if not isinstance(value, str):
value = str(value) value = str(value)
try: try:
uuid.UUID(value) uuid.UUID(value)
@ -2433,7 +2426,7 @@ class LazyReferenceField(BaseField):
document. Note this only work getting field (not setting or deleting). document. Note this only work getting field (not setting or deleting).
""" """
# XXX ValidationError raised outside of the "validate" method. # XXX ValidationError raised outside of the "validate" method.
if not isinstance(document_type, six.string_types) and not issubclass( if not isinstance(document_type, str) and not issubclass(
document_type, Document document_type, Document
): ):
self.error( self.error(
@ -2449,7 +2442,7 @@ class LazyReferenceField(BaseField):
@property @property
def document_type(self): def document_type(self):
if isinstance(self.document_type_obj, six.string_types): if isinstance(self.document_type_obj, str):
if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT: if self.document_type_obj == RECURSIVE_REFERENCE_CONSTANT:
self.document_type_obj = self.owner_document self.document_type_obj = self.owner_document
else: else:

View File

@ -349,20 +349,20 @@ class BaseQuerySet(object):
) )
except pymongo.errors.DuplicateKeyError as err: except pymongo.errors.DuplicateKeyError as err:
message = "Could not save document (%s)" message = "Could not save document (%s)"
raise NotUniqueError(message % six.text_type(err)) raise NotUniqueError(message % err)
except pymongo.errors.BulkWriteError as err: except pymongo.errors.BulkWriteError as err:
# inserting documents that already have an _id field will # inserting documents that already have an _id field will
# give huge performance debt or raise # give huge performance debt or raise
message = u"Bulk write error: (%s)" message = u"Bulk write error: (%s)"
raise BulkWriteError(message % six.text_type(err.details)) raise BulkWriteError(message % err.details)
except pymongo.errors.OperationFailure as err: except pymongo.errors.OperationFailure as err:
message = "Could not save document (%s)" message = "Could not save document (%s)"
if re.match("^E1100[01] duplicate key", six.text_type(err)): if re.match("^E1100[01] duplicate key", str(err)):
# E11000 - duplicate key error index # E11000 - duplicate key error index
# E11001 - duplicate key on update # E11001 - duplicate key on update
message = u"Tried to save duplicate unique keys (%s)" message = u"Tried to save duplicate unique keys (%s)"
raise NotUniqueError(message % six.text_type(err)) raise NotUniqueError(message % err)
raise OperationError(message % six.text_type(err)) raise OperationError(message % err)
# Apply inserted_ids to documents # Apply inserted_ids to documents
for doc, doc_id in zip(docs, ids): for doc, doc_id in zip(docs, ids):
@ -534,12 +534,12 @@ class BaseQuerySet(object):
elif result.raw_result: elif result.raw_result:
return result.raw_result["n"] return result.raw_result["n"]
except pymongo.errors.DuplicateKeyError as err: except pymongo.errors.DuplicateKeyError as err:
raise NotUniqueError(u"Update failed (%s)" % six.text_type(err)) raise NotUniqueError("Update failed (%s)" % err)
except pymongo.errors.OperationFailure as err: except pymongo.errors.OperationFailure as err:
if six.text_type(err) == u"multi not coded yet": if str(err) == "multi not coded yet":
message = u"update() method requires MongoDB 1.1.3+" message = "update() method requires MongoDB 1.1.3+"
raise OperationError(message) raise OperationError(message)
raise OperationError(u"Update failed (%s)" % six.text_type(err)) raise OperationError("Update failed (%s)" % err)
def upsert_one(self, write_concern=None, **update): def upsert_one(self, write_concern=None, **update):
"""Overwrite or add the first document matched by the query. """Overwrite or add the first document matched by the query.
@ -1348,13 +1348,13 @@ class BaseQuerySet(object):
map_f_scope = {} map_f_scope = {}
if isinstance(map_f, Code): if isinstance(map_f, Code):
map_f_scope = map_f.scope map_f_scope = map_f.scope
map_f = six.text_type(map_f) map_f = str(map_f)
map_f = Code(queryset._sub_js_fields(map_f), map_f_scope) map_f = Code(queryset._sub_js_fields(map_f), map_f_scope)
reduce_f_scope = {} reduce_f_scope = {}
if isinstance(reduce_f, Code): if isinstance(reduce_f, Code):
reduce_f_scope = reduce_f.scope reduce_f_scope = reduce_f.scope
reduce_f = six.text_type(reduce_f) reduce_f = str(reduce_f)
reduce_f_code = queryset._sub_js_fields(reduce_f) reduce_f_code = queryset._sub_js_fields(reduce_f)
reduce_f = Code(reduce_f_code, reduce_f_scope) reduce_f = Code(reduce_f_code, reduce_f_scope)
@ -1364,7 +1364,7 @@ class BaseQuerySet(object):
finalize_f_scope = {} finalize_f_scope = {}
if isinstance(finalize_f, Code): if isinstance(finalize_f, Code):
finalize_f_scope = finalize_f.scope finalize_f_scope = finalize_f.scope
finalize_f = six.text_type(finalize_f) finalize_f = str(finalize_f)
finalize_f_code = queryset._sub_js_fields(finalize_f) finalize_f_code = queryset._sub_js_fields(finalize_f)
finalize_f = Code(finalize_f_code, finalize_f_scope) finalize_f = Code(finalize_f_code, finalize_f_scope)
mr_args["finalize"] = finalize_f mr_args["finalize"] = finalize_f
@ -1380,7 +1380,7 @@ class BaseQuerySet(object):
else: else:
map_reduce_function = "map_reduce" map_reduce_function = "map_reduce"
if isinstance(output, six.string_types): if isinstance(output, str):
mr_args["out"] = output mr_args["out"] = output
elif isinstance(output, dict): elif isinstance(output, dict):
@ -1838,7 +1838,7 @@ class BaseQuerySet(object):
field_parts = field.split(".") field_parts = field.split(".")
try: try:
field = ".".join( field = ".".join(
f if isinstance(f, six.string_types) else f.db_field f if isinstance(f, str) else f.db_field
for f in self._document._lookup_field(field_parts) for f in self._document._lookup_field(field_parts)
) )
db_field_paths.append(field) db_field_paths.append(field)
@ -1850,7 +1850,7 @@ class BaseQuerySet(object):
for subdoc in subclasses: for subdoc in subclasses:
try: try:
subfield = ".".join( subfield = ".".join(
f if isinstance(f, six.string_types) else f.db_field f if isinstance(f, str) else f.db_field
for f in subdoc._lookup_field(field_parts) for f in subdoc._lookup_field(field_parts)
) )
db_field_paths.append(subfield) db_field_paths.append(subfield)

View File

@ -101,7 +101,7 @@ def query(_doc_cls=None, **kwargs):
cleaned_fields = [] cleaned_fields = []
for field in fields: for field in fields:
append_field = True append_field = True
if isinstance(field, six.string_types): if isinstance(field, str):
parts.append(field) parts.append(field)
append_field = False append_field = False
# is last and CachedReferenceField # is last and CachedReferenceField
@ -281,7 +281,7 @@ def update(_doc_cls=None, **update):
appended_sub_field = False appended_sub_field = False
for field in fields: for field in fields:
append_field = True append_field = True
if isinstance(field, six.string_types): if isinstance(field, str):
# Convert the S operator to $ # Convert the S operator to $
if field == "S": if field == "S":
field = "$" field = "$"

View File

@ -89,17 +89,6 @@ class TestDateField(MongoDBTestCase):
assert log.date == d1.date() assert log.date == d1.date()
assert log.date == d2.date() assert log.date == d2.date()
if not six.PY3:
# Pre UTC dates microseconds below 1000 are dropped
# This does not seem to be true in PY3
d1 = datetime.datetime(1969, 12, 31, 23, 59, 59, 999)
d2 = datetime.datetime(1969, 12, 31, 23, 59, 59)
log.date = d1
log.save()
log.reload()
assert log.date == d1.date()
assert log.date == d2.date()
def test_regular_usage(self): def test_regular_usage(self):
"""Tests for regular datetime fields""" """Tests for regular datetime fields"""

View File

@ -98,17 +98,6 @@ class TestDateTimeField(MongoDBTestCase):
assert log.date != d1 assert log.date != d1
assert log.date == d2 assert log.date == d2
if not six.PY3:
# Pre UTC dates microseconds below 1000 are dropped
# This does not seem to be true in PY3
d1 = dt.datetime(1969, 12, 31, 23, 59, 59, 999)
d2 = dt.datetime(1969, 12, 31, 23, 59, 59)
log.date = d1
log.save()
log.reload()
assert log.date != d1
assert log.date == d2
def test_regular_usage(self): def test_regular_usage(self):
"""Tests for regular datetime fields""" """Tests for regular datetime fields"""
@ -213,7 +202,7 @@ class TestDateTimeField(MongoDBTestCase):
# make sure that passing a parsable datetime works # make sure that passing a parsable datetime works
dtd = DTDoc() dtd = DTDoc()
dtd.date = date_str dtd.date = date_str
assert isinstance(dtd.date, six.string_types) assert isinstance(dtd.date, str)
dtd.save() dtd.save()
dtd.reload() dtd.reload()

View File

@ -4445,24 +4445,14 @@ class TestQueryset(unittest.TestCase):
"A0" == "%s" % self.Person.objects.order_by("name").scalar("name").first() "A0" == "%s" % self.Person.objects.order_by("name").scalar("name").first()
) )
assert "A0" == "%s" % self.Person.objects.scalar("name").order_by("name")[0] assert "A0" == "%s" % self.Person.objects.scalar("name").order_by("name")[0]
if six.PY3: assert (
assert ( "['A1', 'A2']"
"['A1', 'A2']" == "%s" % self.Person.objects.order_by("age").scalar("name")[1:3]
== "%s" % self.Person.objects.order_by("age").scalar("name")[1:3] )
) assert (
assert ( "['A51', 'A52']"
"['A51', 'A52']" == "%s" % self.Person.objects.order_by("age").scalar("name")[51:53]
== "%s" % self.Person.objects.order_by("age").scalar("name")[51:53] )
)
else:
assert (
"[u'A1', u'A2']"
== "%s" % self.Person.objects.order_by("age").scalar("name")[1:3]
)
assert (
"[u'A51', u'A52']"
== "%s" % self.Person.objects.order_by("age").scalar("name")[51:53]
)
# with_id and in_bulk # with_id and in_bulk
person = self.Person.objects.order_by("name").first() person = self.Person.objects.order_by("name").first()