PYTHON-856 - as_class -> document_class
This commit changes the name of the as_class option in CodecOptions to document_class, to match the name of the MongoClient option.
This commit is contained in:
parent
fa1466179f
commit
c87424e7af
@ -123,7 +123,7 @@ def _get_string(data, position, obj_end, dummy):
|
||||
|
||||
|
||||
def _get_object(data, position, obj_end, opts):
|
||||
"""Decode a BSON subdocument to opts.as_class or bson.dbref.DBRef."""
|
||||
"""Decode a BSON subdocument to opts.document_class or bson.dbref.DBRef."""
|
||||
obj_size = _UNPACK_INT(data[position:position + 4])[0]
|
||||
end = position + obj_size - 1
|
||||
if data[end:position + obj_size] != b"\x00":
|
||||
@ -235,7 +235,7 @@ def _get_code_w_scope(data, position, obj_end, opts):
|
||||
return Code(code, scope), position
|
||||
|
||||
|
||||
def _get_regex(data, position, dummy, opts):
|
||||
def _get_regex(data, position, dummy0, dummy1):
|
||||
"""Decode a BSON regex to bson.regex.Regex or a python pattern object."""
|
||||
pattern, position = _get_c_string(data, position)
|
||||
bson_flags, position = _get_c_string(data, position)
|
||||
@ -303,7 +303,7 @@ def _element_to_dict(data, position, obj_end, opts):
|
||||
|
||||
def _elements_to_dict(data, position, obj_end, opts):
|
||||
"""Decode a BSON document."""
|
||||
result = opts.as_class()
|
||||
result = opts.document_class()
|
||||
end = obj_end - 1
|
||||
while position < end:
|
||||
(key, value, position) = _element_to_dict(data, position, obj_end, opts)
|
||||
@ -312,11 +312,11 @@ def _elements_to_dict(data, position, obj_end, opts):
|
||||
|
||||
|
||||
def _bson_to_dict(data, opts):
|
||||
"""Decode a BSON string to as_class."""
|
||||
"""Decode a BSON string to document_class."""
|
||||
try:
|
||||
obj_size = _UNPACK_INT(data[:4])[0]
|
||||
except struct.error as e:
|
||||
raise InvalidBSON(str(e))
|
||||
except struct.error as exc:
|
||||
raise InvalidBSON(str(exc))
|
||||
if obj_size != len(data):
|
||||
raise InvalidBSON("invalid object size")
|
||||
if data[obj_size - 1:obj_size] != b"\x00":
|
||||
@ -900,7 +900,7 @@ class BSON(bytes):
|
||||
>>> data = bson.BSON.encode({'a': 1})
|
||||
>>> decoded_doc = bson.BSON.decode(data)
|
||||
<type 'dict'>
|
||||
>>> options = CodecOptions(as_class=collections.OrderedDict)
|
||||
>>> options = CodecOptions(document_class=collections.OrderedDict)
|
||||
>>> decoded_doc = bson.BSON.decode(data, codec_options=options)
|
||||
>>> type(decoded_doc)
|
||||
<class 'collections.OrderedDict'>
|
||||
|
||||
@ -113,26 +113,26 @@ _downcast_and_check(Py_ssize_t size, int extra) {
|
||||
/* Fill out a codec_options_t* from a CodecOptions object. Use with the "O&"
|
||||
* format spec in PyArg_ParseTuple.
|
||||
*
|
||||
* Return 1 on success. options->as_class is a new reference.
|
||||
* Return 1 on success. options->document_class is a new reference.
|
||||
* Return 0 on failure.
|
||||
*/
|
||||
int convert_codec_options(PyObject* options_obj, void* p) {
|
||||
codec_options_t* options = (codec_options_t*)p;
|
||||
if (!PyArg_ParseTuple(options_obj, "Obb",
|
||||
&options->as_class,
|
||||
&options->document_class,
|
||||
&options->tz_aware,
|
||||
&options->uuid_rep)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Py_INCREF(options->as_class);
|
||||
Py_INCREF(options->document_class);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Fill out a codec_options_t* with default options. */
|
||||
void default_codec_options(codec_options_t* options) {
|
||||
options->as_class = (PyObject*)&PyDict_Type;
|
||||
Py_INCREF(options->as_class);
|
||||
options->document_class = (PyObject*)&PyDict_Type;
|
||||
Py_INCREF(options->document_class);
|
||||
|
||||
// TODO: set to "1". PYTHON-526, setting tz_aware=True by default.
|
||||
options->tz_aware = 0;
|
||||
@ -140,7 +140,7 @@ void default_codec_options(codec_options_t* options) {
|
||||
}
|
||||
|
||||
void destroy_codec_options(codec_options_t* options) {
|
||||
Py_CLEAR(options->as_class);
|
||||
Py_CLEAR(options->document_class);
|
||||
}
|
||||
|
||||
static PyObject* elements_to_dict(PyObject* self, const char* string,
|
||||
@ -2223,7 +2223,7 @@ static PyObject* _elements_to_dict(PyObject* self, const char* string,
|
||||
unsigned max,
|
||||
const codec_options_t* options) {
|
||||
unsigned position = 0;
|
||||
PyObject* dict = PyObject_CallObject(options->as_class, NULL);
|
||||
PyObject* dict = PyObject_CallObject(options->document_class, NULL);
|
||||
if (!dict) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ typedef int Py_ssize_t;
|
||||
#endif
|
||||
|
||||
typedef struct codec_options_t {
|
||||
PyObject* as_class;
|
||||
PyObject* document_class;
|
||||
unsigned char tz_aware;
|
||||
unsigned char uuid_rep;
|
||||
} codec_options_t;
|
||||
|
||||
@ -21,15 +21,15 @@ from bson.binary import (ALL_UUID_REPRESENTATIONS,
|
||||
UUID_REPRESENTATION_NAMES)
|
||||
|
||||
|
||||
_options_base = namedtuple('CodecOptions',
|
||||
('as_class', 'tz_aware', 'uuid_representation'))
|
||||
_options_base = namedtuple(
|
||||
'CodecOptions', ('document_class', 'tz_aware', 'uuid_representation'))
|
||||
|
||||
|
||||
class CodecOptions(_options_base):
|
||||
"""Encapsulates BSON options used in CRUD operations.
|
||||
|
||||
:Parameters:
|
||||
- `as_class`: BSON documents returned in queries will be decoded
|
||||
- `document_class`: BSON documents returned in queries will be decoded
|
||||
to an instance of this class. Must be a subclass of
|
||||
:class:`~collections.MutableMapping`. Defaults to :class:`dict`.
|
||||
- `tz_aware`: If ``True``, BSON datetimes will be decoded to timezone
|
||||
@ -40,10 +40,10 @@ class CodecOptions(_options_base):
|
||||
:data:`~bson.binary.PYTHON_LEGACY`.
|
||||
"""
|
||||
|
||||
def __new__(cls, as_class=dict,
|
||||
def __new__(cls, document_class=dict,
|
||||
tz_aware=False, uuid_representation=PYTHON_LEGACY):
|
||||
if not issubclass(as_class, MutableMapping):
|
||||
raise TypeError("as_class must be dict, bson.son.SON, or "
|
||||
if not issubclass(document_class, MutableMapping):
|
||||
raise TypeError("document_class must be dict, bson.son.SON, or "
|
||||
"another subclass of collections.MutableMapping")
|
||||
if not isinstance(tz_aware, bool):
|
||||
raise TypeError("tz_aware must be True or False")
|
||||
@ -51,18 +51,20 @@ class CodecOptions(_options_base):
|
||||
raise ValueError("uuid_representation must be a value "
|
||||
"from bson.binary.ALL_UUID_REPRESENTATIONS")
|
||||
|
||||
return tuple.__new__(cls, (as_class, tz_aware, uuid_representation))
|
||||
return tuple.__new__(
|
||||
cls, (document_class, tz_aware, uuid_representation))
|
||||
|
||||
def __repr__(self):
|
||||
as_class_repr = (
|
||||
'dict' if self.as_class is dict else repr(self.as_class))
|
||||
document_class_repr = (
|
||||
'dict' if self.document_class is dict
|
||||
else repr(self.document_class))
|
||||
|
||||
uuid_rep_repr = UUID_REPRESENTATION_NAMES.get(self.uuid_representation,
|
||||
self.uuid_representation)
|
||||
|
||||
return (
|
||||
'CodecOptions(as_class=%s, tz_aware=%r, uuid_representation=%s)'
|
||||
% (as_class_repr, self.tz_aware, uuid_rep_repr))
|
||||
'CodecOptions(document_class=%s, tz_aware=%r, uuid_representation='
|
||||
'%s)' % (document_class_repr, self.tz_aware, uuid_rep_repr))
|
||||
|
||||
|
||||
DEFAULT_CODEC_OPTIONS = CodecOptions()
|
||||
@ -71,8 +73,8 @@ DEFAULT_CODEC_OPTIONS = CodecOptions()
|
||||
def _parse_codec_options(options):
|
||||
"""Parse BSON codec options."""
|
||||
return CodecOptions(
|
||||
as_class=options.get(
|
||||
'document_class', DEFAULT_CODEC_OPTIONS.as_class),
|
||||
document_class=options.get(
|
||||
'document_class', DEFAULT_CODEC_OPTIONS.document_class),
|
||||
tz_aware=options.get(
|
||||
'tz_aware', DEFAULT_CODEC_OPTIONS.tz_aware),
|
||||
uuid_representation=options.get(
|
||||
|
||||
@ -141,9 +141,9 @@ collection, configured to use :class:`~bson.son.SON` instead of dict:
|
||||
.. doctest:: key-order
|
||||
|
||||
>>> from bson import CodecOptions, SON
|
||||
>>> opts = CodecOptions(as_class=SON)
|
||||
>>> opts = CodecOptions(document_class=SON)
|
||||
>>> opts # doctest: +NORMALIZE_WHITESPACE
|
||||
CodecOptions(as_class=<class 'bson.son.SON'>,
|
||||
CodecOptions(document_class=<class 'bson.son.SON'>,
|
||||
tz_aware=False,
|
||||
uuid_representation=PYTHON_LEGACY)
|
||||
>>> collection_son = collection.with_options(codec_options=opts)
|
||||
|
||||
@ -1288,7 +1288,7 @@ class Collection(common.BaseObject):
|
||||
cmd = SON([("listIndexes", self.__name), ("cursor", {})])
|
||||
res, addr = self._command(cmd,
|
||||
ReadPreference.PRIMARY,
|
||||
CodecOptions(as_class=SON))
|
||||
CodecOptions(document_class=SON))
|
||||
# MongoDB 2.8rc2
|
||||
if "indexes" in res:
|
||||
raw = res["indexes"]
|
||||
@ -1298,7 +1298,7 @@ class Collection(common.BaseObject):
|
||||
else:
|
||||
raw = self.__database.get_collection(
|
||||
"system.indexes",
|
||||
codec_options=CodecOptions(as_class=SON),
|
||||
codec_options=CodecOptions(document_class=SON),
|
||||
read_preference=ReadPreference.PRIMARY).find(
|
||||
{"ns": self.__full_name}, {"ns": 0})
|
||||
info = {}
|
||||
|
||||
@ -132,7 +132,7 @@ class TestBSON(unittest.TestCase):
|
||||
|
||||
def encode_then_decode(doc):
|
||||
return doc_class(doc) == BSON.encode(doc).decode(
|
||||
CodecOptions(as_class=doc_class))
|
||||
CodecOptions(document_class=doc_class))
|
||||
|
||||
qcheck.check_unittest(self, encode_then_decode,
|
||||
qcheck.gen_mongo_dict(3))
|
||||
@ -590,16 +590,17 @@ class TestBSON(unittest.TestCase):
|
||||
self.assertIsInstance(BSON.encode({}).decode(), dict)
|
||||
self.assertNotIsInstance(BSON.encode({}).decode(), SON)
|
||||
self.assertIsInstance(
|
||||
BSON.encode({}).decode(CodecOptions(as_class=SON)),
|
||||
BSON.encode({}).decode(CodecOptions(document_class=SON)),
|
||||
SON)
|
||||
|
||||
self.assertEqual(
|
||||
1,
|
||||
BSON.encode({"x": 1}).decode(CodecOptions(as_class=SON))["x"])
|
||||
BSON.encode({"x": 1}).decode(
|
||||
CodecOptions(document_class=SON))["x"])
|
||||
|
||||
x = BSON.encode({"x": [{"y": 1}]})
|
||||
self.assertIsInstance(x.decode(CodecOptions(as_class=SON))["x"][0],
|
||||
SON)
|
||||
self.assertIsInstance(
|
||||
x.decode(CodecOptions(document_class=SON))["x"][0], SON)
|
||||
|
||||
def test_subclasses(self):
|
||||
# make sure we can serialize subclasses of native Python types.
|
||||
@ -630,7 +631,7 @@ class TestBSON(unittest.TestCase):
|
||||
d = OrderedDict([("one", 1), ("two", 2), ("three", 3), ("four", 4)])
|
||||
self.assertEqual(
|
||||
d,
|
||||
BSON.encode(d).decode(CodecOptions(as_class=OrderedDict)))
|
||||
BSON.encode(d).decode(CodecOptions(document_class=OrderedDict)))
|
||||
|
||||
def test_bson_regex(self):
|
||||
# Invalid Python regex, though valid PCRE.
|
||||
@ -764,9 +765,9 @@ class TestBSON(unittest.TestCase):
|
||||
|
||||
|
||||
class TestCodecOptions(unittest.TestCase):
|
||||
def test_as_class(self):
|
||||
self.assertRaises(TypeError, CodecOptions, as_class=object)
|
||||
self.assertIs(SON, CodecOptions(as_class=SON).as_class)
|
||||
def test_document_class(self):
|
||||
self.assertRaises(TypeError, CodecOptions, document_class=object)
|
||||
self.assertIs(SON, CodecOptions(document_class=SON).document_class)
|
||||
|
||||
def test_tz_aware(self):
|
||||
self.assertRaises(TypeError, CodecOptions, tz_aware=1)
|
||||
@ -779,15 +780,15 @@ class TestCodecOptions(unittest.TestCase):
|
||||
self.assertRaises(ValueError, CodecOptions, uuid_representation=2)
|
||||
|
||||
def test_codec_options_repr(self):
|
||||
r = ('CodecOptions(as_class=dict, tz_aware=False, '
|
||||
r = ('CodecOptions(document_class=dict, tz_aware=False, '
|
||||
'uuid_representation=PYTHON_LEGACY)')
|
||||
self.assertEqual(r, repr(CodecOptions()))
|
||||
|
||||
def test_decode_all_defaults(self):
|
||||
# Test decode_all()'s default as_class is dict and tz_aware is False.
|
||||
# The default uuid_representation is PYTHON_LEGACY but this decodes
|
||||
# same as STANDARD, so all this test proves about UUID decoding is
|
||||
# that it's not CSHARP_LEGACY or JAVA_LEGACY.
|
||||
# Test decode_all()'s default document_class is dict and tz_aware is
|
||||
# False. The default uuid_representation is PYTHON_LEGACY but this
|
||||
# decodes same as STANDARD, so all this test proves about UUID decoding
|
||||
# is that it's not CSHARP_LEGACY or JAVA_LEGACY.
|
||||
doc = {'sub_document': {},
|
||||
'uuid': uuid.uuid4(),
|
||||
'dt': datetime.datetime.utcnow()}
|
||||
|
||||
@ -41,8 +41,7 @@ from pymongo.errors import (AutoReconnect,
|
||||
OperationFailure,
|
||||
CursorNotFound,
|
||||
NetworkTimeout,
|
||||
InvalidURI,
|
||||
ServerSelectionTimeoutError)
|
||||
InvalidURI)
|
||||
from pymongo.mongo_client import MongoClient
|
||||
from pymongo.pool import SocketInfo
|
||||
from pymongo.read_preferences import ReadPreference
|
||||
@ -462,14 +461,14 @@ class TestClient(IntegrationTest):
|
||||
db = c.pymongo_test
|
||||
db.test.insert_one({"x": 1})
|
||||
|
||||
self.assertEqual(dict, c.codec_options.as_class)
|
||||
self.assertEqual(dict, c.codec_options.document_class)
|
||||
self.assertTrue(isinstance(db.test.find_one(), dict))
|
||||
self.assertFalse(isinstance(db.test.find_one(), SON))
|
||||
|
||||
c = rs_or_single_client(document_class=SON)
|
||||
db = c.pymongo_test
|
||||
|
||||
self.assertEqual(SON, c.codec_options.as_class)
|
||||
self.assertEqual(SON, c.codec_options.document_class)
|
||||
self.assertTrue(isinstance(db.test.find_one(), SON))
|
||||
|
||||
|
||||
|
||||
@ -544,7 +544,7 @@ class TestDatabase(IntegrationTest):
|
||||
("_id", 5)]))
|
||||
|
||||
db = self.client.get_database(
|
||||
"pymongo_test", codec_options=CodecOptions(as_class=SON))
|
||||
"pymongo_test", codec_options=CodecOptions(document_class=SON))
|
||||
cursor = db.test.find()
|
||||
for x in cursor:
|
||||
for (k, v) in x.items():
|
||||
@ -579,7 +579,7 @@ class TestDatabase(IntegrationTest):
|
||||
|
||||
db.test.insert_one({"_id": 4, "foo": "bar"})
|
||||
db = self.client.get_database(
|
||||
"pymongo_test", codec_options=CodecOptions(as_class=SON))
|
||||
"pymongo_test", codec_options=CodecOptions(document_class=SON))
|
||||
self.assertEqual(SON([("foo", "bar")]),
|
||||
db.dereference(DBRef("test", 4),
|
||||
projection={"_id": False}))
|
||||
|
||||
@ -120,7 +120,7 @@ class TestLegacy(IntegrationTest):
|
||||
doc_class = SON
|
||||
|
||||
db = self.client.get_database(
|
||||
db.name, codec_options=CodecOptions(as_class=doc_class))
|
||||
db.name, codec_options=CodecOptions(document_class=doc_class))
|
||||
|
||||
def remove_insert_find_one(doc):
|
||||
db.test.remove({})
|
||||
@ -770,7 +770,7 @@ class TestLegacy(IntegrationTest):
|
||||
new=True, fields={'i': 1})
|
||||
self.assertFalse(isinstance(result, ExtendedDict))
|
||||
c = self.db.get_collection(
|
||||
"test", codec_options=CodecOptions(as_class=ExtendedDict))
|
||||
"test", codec_options=CodecOptions(document_class=ExtendedDict))
|
||||
result = c.find_and_modify({'_id': 1}, {'$inc': {'i': 1}},
|
||||
new=True, fields={'i': 1})
|
||||
self.assertTrue(isinstance(result, ExtendedDict))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user