def object_hook(dct): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: secs = float(dct["$date"]) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) if "$regex" in dct: flags = 0 if "i" in dct["$options"]: flags |= re.IGNORECASE if "m" in dct["$options"]: flags |= re.MULTILINE return re.compile(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: if isinstance(dct["$type"], int): dct["$type"] = "%02x" % dct["$type"] subtype = int(dct["$type"], 16) if subtype >= 0xffffff80: # Handle mongoexport values subtype = int(dct["$type"][6:], 16) return Binary(base64.b64decode(dct["$binary"].encode()), subtype) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) return dct
def object_hook(dct): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: secs = float(dct["$date"]) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) if "$regex" in dct: flags = 0 # PyMongo always adds $options but some other tools may not. for opt in dct.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) return re.compile(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: if isinstance(dct["$type"], int): dct["$type"] = "%02x" % dct["$type"] subtype = int(dct["$type"], 16) if subtype >= 0xffffff80: # Handle mongoexport values subtype = int(dct["$type"][6:], 16) return Binary(base64.b64decode(dct["$binary"].encode()), subtype) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) return dct
def object_hook(dct, compile_re=True): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: secs = float(dct["$date"]) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) if "$regex" in dct: flags = 0 # PyMongo always adds $options but some other tools may not. for opt in dct.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) if compile_re: return re.compile(dct["$regex"], flags) else: return Regex(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: if isinstance(dct["$type"], int): dct["$type"] = "%02x" % dct["$type"] subtype = int(dct["$type"], 16) if subtype >= 0xffffff80: # Handle mongoexport values subtype = int(dct["$type"][6:], 16) return Binary(base64.b64decode(dct["$binary"].encode()), subtype) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) return dct
def object_hook(dct): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: secs = float(dct["$date"]) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) if "$regex" in dct: flags = 0 if "i" in dct["$options"]: flags |= re.IGNORECASE if "m" in dct["$options"]: flags |= re.MULTILINE return re.compile(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: return Binary(base64.b64decode(dct["$binary"].encode()), dct["$type"]) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) return dct
def json_default(obj): # Modified version from bson package # We preserve key order when rendering SON, DBRef, etc. as JSON by # returning a SON for those types instead of a dict. This works with # the "json" standard library in Python 2.6+ and with simplejson # 2.1.0+ in Python 2.5+, because those libraries iterate the SON # using PyIter_Next. Python 2.4 must use simplejson 2.0.9 or older, # and those versions of simplejson use the lower-level PyDict_Next, # which bypasses SON's order-preserving iteration, so we lose key # order in Python 2.4. if isinstance(obj, bson.ObjectId): return str(obj) if isinstance(obj, bson.DBRef): return bson.json_util._json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): return obj.isoformat() # if isinstance(obj, bson.Timestamp): # return bson.SON([("t", obj.time), ("i", obj.inc)]) # if isinstance(obj, bson.Code): # return bson.SON([('$code', str(obj)), ('$scope', obj.scope)]) # if isinstance(obj, bson.Binary): # return bson.SON([ # ('$binary', base64.b64encode(obj).decode()), # ('$type', "%02x" % obj.subtype)]) # if PY3 and isinstance(obj, binary_type): # return bson.SON([ # ('$binary', base64.b64encode(obj).decode()), # ('$type', "00")]) if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return obj.hex raise TypeError("%r is not JSON serializable" % obj)
def default(obj): # We preserve key order when rendering SON, DBRef, etc. as JSON by # returning a SON for those types instead of a dict. This works with # the "json" standard library in Python 2.6+ and with simplejson # 2.1.0+ in Python 2.5+, because those libraries iterate the SON # using PyIter_Next. Python 2.4 must use simplejson 2.0.9 or older, # and those versions of simplejson use the lower-level PyDict_Next, # which bypasses SON's order-preserving iteration, so we lose key # order in Python 2.4. if isinstance(obj, ObjectId): return {"$oid": str(obj)} if isinstance(obj, DBRef): return _json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? if obj.utcoffset() is not None: obj = obj - obj.utcoffset() millis = int(calendar.timegm(obj.timetuple()) * 1000 + obj.microsecond / 1000) return {"$date": millis} if isinstance(obj, (RE_TYPE, Regex)): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" if isinstance(obj.pattern, str): pattern = obj.pattern else: pattern = obj.pattern.decode('utf-8') return SON([("$regex", pattern), ("$options", flags)]) if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return SON([("t", obj.time), ("i", obj.inc)]) if isinstance(obj, Code): return SON([('$code', str(obj)), ('$scope', obj.scope)]) if isinstance(obj, Binary): return SON([ ('$binary', base64.b64encode(obj).decode()), ('$type', "%02x" % obj.subtype)]) if PY3 and isinstance(obj, binary_type): return SON([ ('$binary', base64.b64encode(obj).decode()), ('$type', "00")]) if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def default(obj): # We preserve key order when rendering SON, DBRef, etc. as JSON by # returning a SON for those types instead of a dict. This works with # the "json" standard library in Python 2.6+ and with simplejson # 2.1.0+ in Python 2.5+, because those libraries iterate the SON # using PyIter_Next. Python 2.4 must use simplejson 2.0.9 or older, # and those versions of simplejson use the lower-level PyDict_Next, # which bypasses SON's order-preserving iteration, so we lose key # order in Python 2.4. if isinstance(obj, ObjectId): return {"$oid": str(obj)} if isinstance(obj, DBRef): return _json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? if obj.utcoffset() is not None: obj = obj - obj.utcoffset() millis = int(calendar.timegm(obj.timetuple()) * 1000 + obj.microsecond / 1000) return {"$date": millis} if isinstance(obj, (RE_TYPE, Regex)): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" if isinstance(obj.pattern, unicode): pattern = obj.pattern else: pattern = obj.pattern.decode('utf-8') return SON([("$regex", pattern), ("$options", flags)]) if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return {"$timestamp": SON([("t", obj.time), ("i", obj.inc)])} if isinstance(obj, Code): return SON([('$code', str(obj)), ('$scope', obj.scope)]) if isinstance(obj, Binary): return SON([ ('$binary', base64.b64encode(obj).decode()), ('$type', "%02x" % obj.subtype)]) if PY3 and isinstance(obj, binary_type): return SON([ ('$binary', base64.b64encode(obj).decode()), ('$type', "00")]) if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def object_hook(dct, compile_re=True): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$numberLong" in dct: return int(dct["$numberLong"]) if "$decimal" in dct: v = str(dct["$decimal"]) if "$precision" in dct: precision = dct["$precision"][0] scale = dct["$precision"][1] d = Decimal(v, precision, scale) else: d = Decimal(v) return d if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: try: secs = float(dct["$date"]) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) except ValueError: return datetime.datetime.strptime(dct["$date"], "%Y-%m-%d") if "$timestamp" in dct: try: ms = long_type(dct["$timestamp"]) return Timestamp(ms / 1000, ms % 1000 * 1000) except ValueError: dt = datetime.datetime.strptime(dct["$timestamp"], "%Y-%m-%d-%H.%M.%S.%f") secs = long_type(time.mktime(dt.timetuple())) return Timestamp(secs, dt.microsecond) if "$regex" in dct: flags = 0 # PyMongo always adds $options but some other tools may not. for opt in dct.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) if compile_re: return re.compile(dct["$regex"], flags) else: return Regex(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: if isinstance(dct["$type"], int): dct["$type"] = "%d" % dct["$type"] subtype = int(dct["$type"]) return Binary(base64.b64decode(dct["$binary"].encode()), subtype) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) return dct
def default(obj): if isinstance(obj, ObjectId): return str(obj) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? if obj.utcoffset() is not None: obj = obj - obj.utcoffset() millis = int(calendar.timegm(obj.timetuple()) * 1000 + obj.microsecond / 1000) return millis if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return obj.hex raise TypeError("%r is not JSON serializable" % obj)
def default(obj): if isinstance(obj, ObjectId): return str(obj) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? if obj.utcoffset() is not None: obj = obj - obj.utcoffset() millis = int( calendar.timegm(obj.timetuple()) * 1000 + obj.microsecond / 1000) return millis if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return obj.hex raise TypeError("%r is not JSON serializable" % obj)
def default(obj): if isinstance(obj,Document) or isinstance(obj,EmbeddedDocument): return obj.to_mongo() if isinstance(obj, ObjectId): return {"$oid": str(obj)} if isinstance(obj, DBRef): return _json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? if obj.utcoffset() is not None: obj = obj - obj.utcoffset() millis = int(calendar.timegm(obj.timetuple()) * 1000 + obj.microsecond / 1000) return {"$date": millis} if isinstance(obj, RE_TYPE): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" return {"$regex": obj.pattern, "$options": flags} if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return {"t": obj.time, "i": obj.inc} if isinstance(obj, Code): return {'$code': "%s" % obj, '$scope': obj.scope} if isinstance(obj, Binary): return {'$binary': base64.b64encode(obj).decode(), '$type': "%02x" % obj.subtype} if PY3 and isinstance(obj, binary_type): return {'$binary': base64.b64encode(obj).decode(), '$type': "00"} if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def default(obj): if isinstance(obj, ObjectId): return {"$oid": str(obj)} if isinstance(obj, DBRef): return _json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? if obj.utcoffset() is not None: obj = obj - obj.utcoffset() millis = int(calendar.timegm(obj.timetuple()) * 1000 + obj.microsecond / 1000) return {"$date": millis} if isinstance(obj, RE_TYPE): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" return {"$regex": obj.pattern, "$options": flags} if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return {"t": obj.time, "i": obj.inc} if isinstance(obj, Code): return {'$code': "%s" % obj, '$scope': obj.scope} if isinstance(obj, Binary): return {'$binary': base64.b64encode(obj).decode(), '$type': "%02x" % obj.subtype} if PY3 and isinstance(obj, binary_type): return {'$binary': base64.b64encode(obj).decode(), '$type': "00"} if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def default(obj, date_func=None): if isinstance(obj, ObjectId): return urlsafe_base64_encode(obj.binary).decode('utf8') if isinstance(obj, DBRef): return _json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): return date_func(obj) if isinstance(obj, RE_TYPE): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" return {"$regex": obj.pattern, "$options": flags} if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return SON([("t", obj.time), ("i", obj.inc)]) if isinstance(obj, Code): return SON([('$code', str(obj)), ('$scope', obj.scope)]) if isinstance(obj, Binary): return SON([ ('$binary', base64.b64encode(obj).decode()), ('$type', "%02x" % obj.subtype)]) if PY3 and isinstance(obj, binary_type): return SON([ ('$binary', base64.b64encode(obj).decode()), ('$type', "00")]) if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def default(obj): if isinstance(obj, ObjectId): # return { "$oid": str(obj) } return str(obj) if isinstance(obj, DBRef): return obj.as_doc() if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? # if obj.utcoffset() is not None: # obj = obj - obj.utcoffset() # millis = int(calendar.timegm(obj.timetuple()) * 1000 + # obj.microsecond / 1000) # return {"$date": millis} return obj.isoformat() if isinstance(obj, _RE_TYPE): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.MULTILINE: flags += "m" return {"$regex": obj.pattern, "$options": flags} if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): return {"t": obj.time, "i": obj.inc} if isinstance(obj, Code): return {"$code": "%s" % obj, "$scope": obj.scope} if isinstance(obj, Binary): return {"$binary": base64.b64encode(obj).decode(), "$type": obj.subtype} if PY3 and isinstance(obj, binary_type): return {"$binary": base64.b64encode(obj).decode(), "$type": 0} if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def object_hook(dct, compile_re=True): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: dtm = dct["$date"] # mongoexport 2.6 and newer if isinstance(dtm, str): # datetime.datetime.strptime is new in python 2.5 naive = datetime.datetime( *(time.strptime(dtm[:19], "%Y-%m-%dT%H:%M:%S")[0:6])) # The %f format is new in python 2.6 micros = int(dtm[20:23]) * 1000 aware = naive.replace(microsecond=micros, tzinfo=utc) offset = dtm[23:] if not offset or offset == 'Z': # UTC return aware else: if len(offset) == 5: # Offset from mongoexport is in format (+|-)HHMM secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60) elif ':' in offset and len(offset) == 6: # RFC-3339 format (+|-)HH:MM hours, minutes = offset[1:].split(':') secs = (int(hours) * 3600 + int(minutes) * 60) else: # Not RFC-3339 compliant or mongoexport output. raise ValueError("invalid format for offset") if offset[0] == "-": secs *= -1 return aware - datetime.timedelta(seconds=secs) # mongoexport 2.6 and newer, time before the epoch (SERVER-15275) elif isinstance(dtm, dict): secs = float(dtm["$numberLong"]) / 1000.0 # mongoexport before 2.6 else: secs = float(dtm) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) if "$regex" in dct: flags = 0 # PyMongo always adds $options but some other tools may not. for opt in dct.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) if compile_re: return re.compile(dct["$regex"], flags) else: return Regex(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: if isinstance(dct["$type"], int): dct["$type"] = "%02x" % dct["$type"] subtype = int(dct["$type"], 16) if subtype >= 0xffffff80: # Handle mongoexport values subtype = int(dct["$type"][6:], 16) return Binary(base64.b64decode(dct["$binary"].encode()), subtype) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) if "$undefined" in dct: return None if "$numberLong" in dct: # 2to3 will change this to int. PyMongo 3.0 supports # a new type, Int64, to avoid round trip issues. return int(dct["$numberLong"]) if "$timestamp" in dct: tsp = dct["$timestamp"] return Timestamp(tsp["t"], tsp["i"]) return dct
def default(obj): # We preserve key order when rendering SON, DBRef, etc. as JSON by # returning a SON for those types instead of a dict. This works with # the "json" standard library in Python 2.6+ and with simplejson # 2.1.0+ in Python 2.5+, because those libraries iterate the SON # using PyIter_Next. Python 2.4 must use simplejson 2.0.9 or older, # and those versions of simplejson use the lower-level PyDict_Next, # which bypasses SON's order-preserving iteration, so we lose key # order in Python 2.4. if isinstance(obj, ObjectId): return {"$oid": str(obj)} if isinstance(obj, int) or ((not PY3) and isinstance(obj, long)): if (obj > 9007199254740991 or obj < -9007199254740991) and get_js_compatibility(): return {"$numberLong": str(obj)} if isinstance(obj, Decimal): return json.loads(str(obj), object_pairs_hook=OrderedDict) if isinstance(obj, DBRef): return _json_convert(obj.as_doc()) if isinstance(obj, datetime.datetime): # TODO share this code w/ bson.py? # if obj.utcoffset() is not None: # obj = obj - obj.utcoffset() # millis = int(calendar.timegm(obj.timetuple()) * 1000 + # obj.microsecond / 1000) # PY2 do not support year before 1900 return {"$date": "{0.year:04d}-{0.month:02d}-{0.day:02d}".format(obj)} if isinstance(obj, (RE_TYPE, Regex)): flags = "" if obj.flags & re.IGNORECASE: flags += "i" if obj.flags & re.LOCALE: flags += "l" if obj.flags & re.MULTILINE: flags += "m" if obj.flags & re.DOTALL: flags += "s" if obj.flags & re.UNICODE: flags += "u" if obj.flags & re.VERBOSE: flags += "x" if isinstance(obj.pattern, text_type): pattern = obj.pattern else: pattern = obj.pattern.decode('utf-8') return SON([("$regex", pattern), ("$options", flags)]) if isinstance(obj, MinKey): return {"$minKey": 1} if isinstance(obj, MaxKey): return {"$maxKey": 1} if isinstance(obj, Timestamp): dt = time.strftime("%Y-%m-%d-%H.%M.%S", time.localtime( obj.time)) + "." + "{:06d}".format(obj.inc) return {"$timestamp": dt} if isinstance(obj, Code): return SON([('$code', str(obj)), ('$scope', obj.scope)]) if isinstance(obj, Binary): return SON([('$binary', base64.b64encode(obj).decode()), ('$type', "%d" % obj.subtype)]) if PY3 and isinstance(obj, binary_type): return SON([('$binary', base64.b64encode(obj).decode()), ('$type', "0")]) if bson.has_uuid() and isinstance(obj, bson.uuid.UUID): return {"$uuid": obj.hex} raise TypeError("%r is not JSON serializable" % obj)
def test_uuid(self): if not bson.has_uuid(): raise SkipTest("No uuid module") self.round_trip( {'uuid': bson.uuid.UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')})
def object_hook(dct, compile_re=True): if "$oid" in dct: return ObjectId(str(dct["$oid"])) if "$ref" in dct: return DBRef(dct["$ref"], dct["$id"], dct.get("$db", None)) if "$date" in dct: dtm = dct["$date"] # mongoexport 2.6 and newer if isinstance(dtm, basestring): # datetime.datetime.strptime is new in python 2.5 naive = datetime.datetime( *(time.strptime(dtm[:19], "%Y-%m-%dT%H:%M:%S")[0:6])) # The %f format is new in python 2.6 micros = int(dtm[20:23]) * 1000 aware = naive.replace(microsecond=micros, tzinfo=utc) offset = dtm[23:] if not offset or offset == 'Z': # UTC return aware else: if len(offset) == 5: # Offset from mongoexport is in format (+|-)HHMM secs = (int(offset[1:3]) * 3600 + int(offset[3:]) * 60) elif ':' in offset and len(offset) == 6: # RFC-3339 format (+|-)HH:MM hours, minutes = offset[1:].split(':') secs = (int(hours) * 3600 + int(minutes) * 60) else: # Not RFC-3339 compliant or mongoexport output. raise ValueError("invalid format for offset") if offset[0] == "-": secs *= -1 return aware - datetime.timedelta(seconds=secs) # mongoexport 2.6 and newer, time before the epoch (SERVER-15275) elif isinstance(dtm, dict): secs = float(dtm["$numberLong"]) / 1000.0 # mongoexport before 2.6 else: secs = float(dtm) / 1000.0 return EPOCH_AWARE + datetime.timedelta(seconds=secs) if "$regex" in dct: flags = 0 # PyMongo always adds $options but some other tools may not. for opt in dct.get("$options", ""): flags |= _RE_OPT_TABLE.get(opt, 0) if compile_re: return re.compile(dct["$regex"], flags) else: return Regex(dct["$regex"], flags) if "$minKey" in dct: return MinKey() if "$maxKey" in dct: return MaxKey() if "$binary" in dct: if isinstance(dct["$type"], int): dct["$type"] = "%02x" % dct["$type"] subtype = int(dct["$type"], 16) if subtype >= 0xffffff80: # Handle mongoexport values subtype = int(dct["$type"][6:], 16) return Binary(base64.b64decode(dct["$binary"].encode()), subtype) if "$code" in dct: return Code(dct["$code"], dct.get("$scope")) if bson.has_uuid() and "$uuid" in dct: return bson.uuid.UUID(dct["$uuid"]) if "$undefined" in dct: return None if "$numberLong" in dct: # 2to3 will change this to int. PyMongo 3.0 supports # a new type, Int64, to avoid round trip issues. return long(dct["$numberLong"]) if "$timestamp" in dct: tsp = dct["$timestamp"] return Timestamp(tsp["t"], tsp["i"]) return dct
def test_uuid(self): if not bson.has_uuid(): raise SkipTest("No uuid module") self.round_trip( {'uuid': bson.uuid.UUID( 'f47ac10b-58cc-4372-a567-0e02b2c3d479')})