|
70 | 70 | import base64 |
71 | 71 | import collections |
72 | 72 | import datetime |
73 | | -import json |
74 | 73 | import re |
| 74 | +import sys |
75 | 75 | import uuid |
76 | 76 |
|
| 77 | +_HAS_OBJECT_PAIRS_HOOK = True |
| 78 | +if sys.version_info[:2] == (2, 6): |
| 79 | + # In Python 2.6, json does not include object_pairs_hook. Use simplejson |
| 80 | + # instead. |
| 81 | + try: |
| 82 | + import simplejson as json |
| 83 | + except ImportError: |
| 84 | + import json |
| 85 | + _HAS_OBJECT_PAIRS_HOOK = False |
| 86 | +else: |
| 87 | + import json |
| 88 | + |
| 89 | +from pymongo.errors import ConfigurationError |
| 90 | + |
77 | 91 | import bson |
78 | 92 | from bson import EPOCH_AWARE, RE_TYPE, SON |
79 | 93 | from bson.binary import (Binary, JAVA_LEGACY, CSHARP_LEGACY, OLD_UUID_SUBTYPE, |
|
106 | 120 | class JSONOptions(CodecOptions): |
107 | 121 | """Encapsulates JSON options for :func:`dumps` and :func:`loads`. |
108 | 122 |
|
| 123 | + Raises :exc:`~pymongo.errors.ConfigurationError` on Python 2.6 if |
| 124 | + `simplejson <https://pypi.python.org/pypi/simplejson>`_ is not installed |
| 125 | + and document_class is not the default (:class:`dict`). |
| 126 | +
|
109 | 127 | :Parameters: |
110 | 128 | - `strict_number_long`: If ``True``, :class:`~bson.int64.Int64` objects |
111 | 129 | are encoded to MongoDB Extended JSON's *Strict mode* type |
@@ -145,6 +163,11 @@ def __new__(cls, strict_number_long=False, strict_date=False, |
145 | 163 | if kwargs["tz_aware"]: |
146 | 164 | kwargs["tzinfo"] = kwargs.get("tzinfo", utc) |
147 | 165 | self = super(JSONOptions, cls).__new__(cls, *args, **kwargs) |
| 166 | + if not _HAS_OBJECT_PAIRS_HOOK and self.document_class != dict: |
| 167 | + raise ConfigurationError( |
| 168 | + "Support for JSONOptions.document_class on Python 2.6 " |
| 169 | + "requires simplejson " |
| 170 | + "(https://pypi.python.org/pypi/simplejson) to be installed.") |
148 | 171 | self.strict_number_long = strict_number_long |
149 | 172 | self.strict_date = strict_date |
150 | 173 | self.strict_uuid = strict_uuid |
@@ -177,7 +200,7 @@ def dumps(obj, *args, **kwargs): |
177 | 200 | Recursive function that handles all BSON types including |
178 | 201 | :class:`~bson.binary.Binary` and :class:`~bson.code.Code`. |
179 | 202 |
|
180 | | - Raises :class:`~bson.errors.InvalidDatetime` if `obj` contains a |
| 203 | + Raises :exc:`~bson.errors.InvalidDatetime` if `obj` contains a |
181 | 204 | :class:`datetime.datetime` without a timezone and |
182 | 205 | `json_options.strict_date` is ``True``. |
183 | 206 |
|
@@ -211,8 +234,11 @@ def loads(s, *args, **kwargs): |
211 | 234 | Accepts optional parameter `json_options`. See :class:`JSONOptions`. |
212 | 235 | """ |
213 | 236 | json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS) |
214 | | - kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook(pairs, |
215 | | - json_options) |
| 237 | + if _HAS_OBJECT_PAIRS_HOOK: |
| 238 | + kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook( |
| 239 | + pairs, json_options) |
| 240 | + else: |
| 241 | + kwargs["object_hook"] = lambda obj: object_hook(obj, json_options) |
216 | 242 | return json.loads(s, *args, **kwargs) |
217 | 243 |
|
218 | 244 |
|
|
0 commit comments