def pushItem(self, path, item): try: result = self.col.find({'public_key': self.get('public_key')}, {'_id': 1}) if result.count() > 0: if type(result[0]['_id']) == type(''): id = ObjectId(result[0]['_id']) else: id = result[0]['_id'] else: self.col.insert(self.get()) del self._data['_id'] result = self.col.find({'public_key': self.get('public_key')}, {'_id': 1}) if type(result[0]['_id']) == type(''): id = ObjectId(result[0]['_id']) else: id = result[0]['_id'] status = self.col.update({'_id': id}, {'$push': {path: item}}) status = self.col.update( {'_id': id}, {'$set': { 'modified': self.setModifiedToNow() }}) return "save ok" except: raise
def admin_update(): db = getDBConnection().upload fs = GridFS(db) id = request.form['id'] if request.form.has_key('approve'): db.fs.files.update({"_id": ObjectId(id)}, {"$set": { "metadata.status": "approved" }}) db.fs.files.update({"metadata.parent_archive_id": ObjectId(id)}, {"$set": { "metadata.status": "approvedchild" }}, multi=1) flask.flash('Approved') if request.form.has_key('disapprove'): db.fs.files.update({"_id": ObjectId(id)}, {"$set": { "metadata.status": "disapproved" }}) db.fs.files.update({"metadata.parent_archive_id": ObjectId(id)}, {"$set": { "metadata.status": "disapprovedchild" }}, multi=1) flask.flash('Disapproved') return flask.redirect(url_for(".admin"))
def curation_detail(request, object_id, index=None, template='depot/curation_detail.html'): if index: resource = get_one_or_404(id=ObjectId(object_id)) curation = resource.curations[int(index)] else: curation = get_one_or_404(obj_class=Curation, id=ObjectId(object_id)) resource = curation.resource if request.is_ajax(): context = { 'curation': { 'note': curation.note, 'tags': curation.tags, }, 'resource': { 'title': resource.title, 'description': resource.description, }, 'url': reverse('curation-add', args=(resource.id, )), } return HttpResponse(json.dumps(context), mimetype='application/json') context = { 'index': index, 'object': curation, 'resource': resource, } return render_to_response(template, RequestContext(request, context))
def POST(self): def update(d, i): for c in column_names(): # input names are not decoded u = c.encode('utf8') if i.has_key(u): d[c] = i.get(u) d['_tags'] = get_tags(d) i = web.input() a = i.get('__action', None) if a == 'add': d = {} update(d, i) o = objs.save(d) o = list(objs.find(d)) return render.index(conf.title, columns(), o, 'add') elif a == 'update': if i.get('_id', None): d = objs.find_one(ObjectId(i['_id'])) if d: update(d, i) oid = objs.save(d) o = [objs.find_one(oid)] return render.index(conf.title, columns(), o, 'update') elif a == 'delete': if i.get('_id', None): objs.remove(ObjectId(i['_id'])) raise web.SeeOther('/') raise web.BadRequest()
def test_generation_time(self): d1 = datetime.datetime.utcnow() d2 = ObjectId().generation_time self.assertEqual(utc, d2.tzinfo) d2 = d2.replace(tzinfo=None) self.assert_(d2 - d1 < datetime.timedelta(seconds = 2))
def test_retrieve_creates_class_instances(self, mongo_conn_class): first_object_id, second_object_id = ObjectId(), ObjectId() self.build_mongo_connection(mongo_conn_class) self.cursor.find.return_value = [ { '_id': first_object_id, 'name': 'first object' }, { '_id': second_object_id, 'name': 'second object' }, ] result = self.storage.retrieve(self.BIN_NAME, storage_id=self.storage_id, cls=TestStorable) self.assertMongoCollectionWas(self.BIN_NAME) self.cursor.find.assert_called_with({'_id': ObjectId(self.storage_id)}) self.assertEquals(len(result), 2) self.assertEquals(result[0].object_id, str(first_object_id)) self.assertEquals(result[0].attributes['name'], 'first object') self.assertEquals(result[1].object_id, str(second_object_id)) self.assertEquals(result[1].attributes['name'], 'second object')
def test_repr(self): self.assertEqual( repr(DBRef("coll", ObjectId("1234567890abcdef12345678"))), "DBRef(u'coll', ObjectId('1234567890abcdef12345678'))") self.assertEqual( repr(DBRef(u"coll", ObjectId("1234567890abcdef12345678"))), "DBRef(u'coll', ObjectId('1234567890abcdef12345678'))")
def _convert_to_python(doc, struct, path = "", root_path=""): for key in struct: if type(key) is type: new_key = '$%s' % key.__name__ else: new_key = key new_path = ".".join([path, new_key]).strip('.') if isinstance(struct[key], dict): if doc: # we don't need to process an empty doc if key in doc: # we don't care about missing fields _convert_to_python(doc[key], struct[key], new_path, root_path) elif type(struct[key]) is list: if struct[key]: if struct[key][0] is datetime.datetime: l_objs = [] for obj in doc[key]: obj = fromtimestamp(obj) l_objs.append(obj) doc[key] = l_objs elif isinstance(struct[key][0], R): l_objs = [] for obj in doc[key]: db = obj.get('_database') or obj.get('$db') col = obj.get('_collection') or obj.get('$ref') if '_id' in obj: id_ref = '_id' if '$oid' in obj['_id']: obj['_id'] = ObjectId(obj['_id']['$oid']) elif '$id' in obj: id_ref = '$id' obj_class = struct[key][0]._doc _id = obj[id_ref] obj = getattr(self.connection[db][col], obj_class.__name__).one({'_id': _id}) #obj = struct[key][0]._doc(obj, collection=self.connection[db][col]).get_dbref() l_objs.append(obj) doc[key] = l_objs elif isinstance(struct[key][0], dict): if doc[key]: for obj in doc[key]: _convert_to_python(obj, struct[key][0], new_path, root_path) elif struct[key] is datetime.datetime and doc[key] is not None: doc[key] = fromtimestamp(doc[key]) elif (isinstance(struct[key], R) or isinstance(struct[key], DocumentProperties)) and doc[key] is not None: db = doc[key].get('_database') or doc[key].get('$db') col = doc[key].get('_collection') or doc[key].get('$ref') if '_id' in doc[key]: id_ref = '_id' elif '$id' in doc[key]: id_ref = '$id' if '$oid' in doc[key][id_ref]: doc[key][id_ref] = ObjectId(doc[key][id_ref]['$oid']) if isinstance(struct[key], R): obj_class = struct[key]._doc else: obj_class = struct[key] #_id = obj_class(doc[key], collection=self.connection[db][col])[id_ref] _id = doc[key][id_ref] doc[key] = getattr(self.connection[db][col], obj_class.__name__).one({'_id': _id})
def get_run_log(self, job_id, task_name, log_id): q = { 'job_id': ObjectId(job_id), 'tasks.%s' % task_name: { '$exists': True }, 'log_id': ObjectId(log_id) } return self.log_coll.find_one(q)['tasks'][task_name]
def GET(self): checkLogin() q = web.input() db.update({'answers.id': ObjectId(q['id'])}, {'$set': { 'answers.$.content': q['content'] }}) question = db.find_one({'answers.id': ObjectId(q['id'])}) return json.dumps({'id': question['_id']}, cls=CJsonEncoder)
def product(): if request.method == 'GET': if 'id' in request.args: try: product = db.products.find_one( {"_id": ObjectId(request.args['id'])}) except InvalidId: return jsonify(response=[]) if (product is None): return jsonify(response=[]) product['_id'] = str(product['_id']) return jsonify(response=[product]) elif 'name' in request.args: product = db.products.find_one({"name": request.args['name']}) if (product is None): return jsonify(response=[]) product['_id'] = str(product['_id']) return jsonify(response=[product]) elif 'prefix' in request.args: products = [] for product in db.products.find( {"name": { "$regex": "^" + request.args['prefix'] + ".*" }}): product['_id'] = str(product['_id']) products.append(product) return jsonify(response=products) else: products = [] for product in db.products.find(): product['_id'] = str(product['_id']) products.append(product) return jsonify(response=products) elif request.method == 'POST': if (request.json is None): return jsonify(error="POST data is not JSON.") db.products.insert(request.json, manipulate=True) request.json['_id'] = str(request.json['_id']) return jsonify(request.json) elif request.method == 'PUT': if (request.json is None): return jsonify(error="PUT data is not JSON.") request.json['_id'] = ObjectId(request.json['_id']) db.products.save(request.json, manipulate=True) request.json['_id'] = str(request.json['_id']) return jsonify(request.json) elif request.method == 'DELETE': if 'id' in request.args: try: db.products.remove({"_id": ObjectId(request.args['id'])}) except InvalidId: return jsonify(response=[]) return jsonify(response="ok") elif 'name' in request.args: db.products.remove({"name": request.args['name']}) return jsonify(response="ok") return jsonify(error="No parameters.") return jsonify(error="This should never happen.")
def test_from_xml(self): smorgasbord = """ <twonk> <meta/> <doc> <oid name="_id">285a664923b5fcd8ec000000</oid> <int name="the_answer">42</int> <string name="b">foo</string> <boolean name="c">true</boolean> <number name="pi">3.14159265358979</number> <array name="an_array"> <string name="0">x</string> <string name="1">y</string> <string name="2">z</string> <doc name="3"> <string name="subobject">yup</string> </doc> </array> <date name="now">123144452057</date> <ref name="dbref"> <ns>namespace</ns> <oid>ca5c67496c01d896f7010000</oid> </ref> <regex name="regex"> <pattern>foobar</pattern> <options>i</options> </regex> <code name="$where">this is code</code> <null name="mynull"/> </doc> </twonk> """ self.assertEqual( SON.from_xml(smorgasbord), SON([ (u"_id", ObjectId("\x28\x5A\x66\x49\x23\xB5\xFC" "\xD8\xEC\x00\x00\x00")), (u"the_answer", 42), (u"b", u"foo"), (u"c", True), (u"pi", 3.14159265358979), (u"an_array", [u"x", u"y", u"z", SON([(u"subobject", u"yup")])]), (u"now", datetime.datetime(1973, 11, 26, 6, 47, 32, 57000)), (u"dbref", DBRef( "namespace", ObjectId("\xCA\x5C\x67\x49\x6C\x01" "\xD8\x96\xF7\x01\x00\x00"))), (u"regex", re.compile(u"foobar", re.IGNORECASE)), (u"$where", "this is code"), (u"mynull", None), ]))
def test_from_datetime(self): d = datetime.datetime.utcnow() d = d - datetime.timedelta(microseconds=d.microsecond) oid = ObjectId.from_datetime(d) self.assertEqual(d, oid.generation_time.replace(tzinfo=None)) self.assertEqual("0" * 16, str(oid)[8:]) aware = datetime.datetime(1993, 4, 4, 2, tzinfo=FixedOffset(555, "SomeZone")) as_utc = (aware - aware.utcoffset()).replace(tzinfo=utc) oid = ObjectId.from_datetime(aware) self.assertEqual(as_utc, oid.generation_time)
def test_retrieve_one_creates_class_instances(self, mongo_conn_class): oid = ObjectId() self.build_mongo_connection(mongo_conn_class) self.cursor.find.return_value = [{'_id': oid, 'name': 'value'}] result = self.storage.retrieve_one(self.BIN_NAME, storage_id=self.storage_id, cls=TestStorable) self.assertMongoCollectionWas(self.BIN_NAME) self.cursor.find.assert_called_with({'_id': ObjectId(self.storage_id)}) self.assertEquals(result.object_id, str(oid)) self.assertEquals(result.attributes['name'], 'value')
def optout(request): response = render_to_response("content_optout.html") user = getCurrentUser(request) coll = getCollDrops() drops = [] for drop in coll.find({"newsrivr_userid_md5":user["newsrivr_userid_md5"]}): coll.remove({"_id":ObjectId(drop["_id"])}) getCollUsers().remove({"_id":ObjectId(user["_id"])}) clog("delete cookie optout") response.delete_cookie("newsrivr_userid_md5"); return response
def test_decode_json(self): self.new_dagobah() now = datetime.datetime.now() test_doc = {"nested": {"dt": now}, "object_id": ObjectId('52220d1e6ba8e11a26c20c9a'), "array": [{"object_id": ObjectId('52220d1e6ba8e11a26c20c9b')}, {"object_id": ObjectId('52220d1e6ba8e11a26c20c9c'), "string": "woot", "int": 5}]} json_doc = json.dumps(test_doc, cls=StrictJSONEncoder) result = self.dagobah.backend.decode_import_json(json_doc) assert result == test_doc
def GET(self): checkLogin() q = web.input() comment = { 'id': ObjectId(), 'content': q['content'], 'author': session.user, 'update_time': datetime.now() } db.update({'_id': ObjectId(q['question_id'])}, {'$push': { 'comments': comment }}) return json.dumps({'id': q['question_id']})
def curation_edit(request, object_id, index, template_name='depot/curation_edit.html'): """Curation is an EmbeddedDocument, so can't be saved, needs to be edited, then Resource saved.""" resource = get_one_or_404(id=ObjectId(object_id), user=request.user, perm='can_edit') object = resource.curations[int(index)] if request.method == 'POST': result = request.POST.get('result', '') if result == 'Cancel': return HttpResponseRedirect( reverse('curation', args=[resource.id, index])) form = CurationForm(request.POST, instance=object) if form.is_valid(): user = get_account(request.user.id) curation = form.save(do_save=False) curation.item_metadata.update(author=user) curation.save() resource.save(reindex=True) return HttpResponseRedirect( reverse('curation', args=[resource.id, index])) else: form = CurationForm(instance=object) template_context = {'form': form} return render_to_response(template_name, template_context, RequestContext(request))
def test_save_find_one(self): db = Database(self.connection, "pymongo_test") db.test.remove({}) a_doc = SON({"hello": u"world"}) a_key = db.test.save(a_doc) self.assert_(isinstance(a_doc["_id"], ObjectId)) self.assertEqual(a_doc["_id"], a_key) self.assertEqual(a_doc, db.test.find_one({"_id": a_doc["_id"]})) self.assertEqual(a_doc, db.test.find_one(a_key)) self.assertEqual(None, db.test.find_one(ObjectId())) self.assertEqual(a_doc, db.test.find_one({"hello": u"world"})) self.assertEqual(None, db.test.find_one({"hello": u"test"})) b = db.test.find_one() b["hello"] = u"mike" db.test.save(b) self.assertNotEqual(a_doc, db.test.find_one(a_key)) self.assertEqual(b, db.test.find_one(a_key)) self.assertEqual(b, db.test.find_one()) count = 0 for _ in db.test.find(): count += 1 self.assertEqual(count, 1)
def download(id, filename): file = GridFS(getDBConnection().upload).get(ObjectId(id)) response = flask.Response(file.__iter__()) response.headers['content-type'] = file.metadata['content_type'] response.content_length = file.length return response
def get_current_user(self): # just the user _id try: u_ = json.loads(self.get_secure_cookie('authed_user')) return models.User.grab(ObjectId(u_['user'])) except: return None
def update(self): """ Update user values in the database """ self.__request_account() self.__request_profile() self.__request_password() if 'file' in request.files and self.__upload_avatar(): self.user['image'] = self.list_images if self.message is None: if len(request.form['password_new']): password_new = create_password(request.form['password_new']) self.user['password'] = password_new # If is changed the username it's important # the old avatars directory in the new position if self.changed_username and len(self.user['image']): src = os.path.join(UP_AVATARS_FOLDER, self.changed_username[0]) dst = os.path.join(UP_AVATARS_FOLDER, self.changed_username[1]) shutil.move(src, dst) try: g.db.users.update({'_id': ObjectId(self.user['_id'])}, self.user) self.status = 'msg msg-success' self.message = g.users_msg('success_update_user') except PyMongoError: self.message = g.users_msg('error_mongo_update')
def remove(self, _id): """ Remove hash map """ try: g.db.hash_table.remove({'_id': ObjectId(_id)}) return 'ok' except PyMongoError: return 'nada'
def clean(self, value): if self.required and not value: raise forms.ValidationError(self.error_messages['required']) elif not self.required and not value: return [] if not isinstance(value, (list, tuple)): raise forms.ValidationError(self.error_messages['list']) key = 'pk' filter_ids = [] for pk in value: try: oid = ObjectId(pk) filter_ids.append(oid) except InvalidId: raise forms.ValidationError( self.error_messages['invalid_pk_value'] % pk) qs = self.queryset.clone() qs = qs.filter(**{'%s__in' % key: filter_ids}) pks = set([force_unicode(getattr(o, key)) for o in qs]) for val in value: if force_unicode(val) not in pks: raise forms.ValidationError( self.error_messages['invalid_choice'] % val) # Since this overrides the inherited ModelChoiceField.clean # we run custom validators here self.run_validators(value) return list(qs)
def detail(eid): back_url = request.args.get('back') entry = db.Entry.find_one({'_id': ObjectId(eid)}) phones = entry['contracts'] # get phone tel = None for e in phones: if not cellphone.match(e): tel = e break if not tel: if len(phones) >= 3: tel = phones[1] else: tel = phones[0] if not entry: abort(404) return render_template('detail.html', back=back_url, tel=tel, is_cell=bool(cellphone.match(tel)), e=entry)
def find_model_instance(self, model_name, model_keys): """Returns a model instance, if one exists, that matches model_name and model_keys. Returns None if no such model instance exists. """ return self.get_model_collection(model_name).find_one( ObjectId(model_keys[0]), as_class=self.get_model_class(model_name))
def get_page(self, _id): """ Get the user document from Database """ try: _id = ObjectId(_id) self.page = g.db.pages.find_one({'_id': _id}) except InvalidId: self.page = {}
def core_before_request(): """ - To run before each request - It's save variable db in the global variable "g" """ g.db = db g.my = None g.languages_object = Languages() # Get all the available languages # e.g. {u'en': u'English', u'it': u'Italiano'} g.available_languages = g.languages_object.get_languages(0) get_headers() # Check that user has login if 'user_id' in session: # get user_id from session user_id = session['user_id'] # get the user's personal data. my = g.db.users.find_one({'_id': ObjectId(user_id)}) # If user_id not exist in the user list g.my is None if my: g.my = my if not "token" in g.my: g.my['token'] = get_token(CLIENT_ID, CLIENT_SECRET, user['username'], user['password']) g.db.users.update({"_id": g.my["_id"]}, user) # get user language g.lan = g.my['lan'] g.language = g.available_languages[g.lan] if my['rank'] < 80: get_hash_admin()
def get_file(self, cell_id, filename): _id = self._conn.fs.files.find_one( { 'cell_id': ObjectId(cell_id), 'filename': filename }, ['_id']) return self._fs.get(_id['_id'])
def tv_lookup(zip_or_id): if zip_or_id: if re.match('\d{5}', zip_or_id): location = g.geo.zipcode_lookup(zip_or_id) if location: center = [location['latitude'], location['longitude']] radius = getattr(settings, "TV_LOOKUP_RADIUS", 1.25) res = g.db.tvstations.find({ "power": "high", "location": { "$within": { "$center": [center, radius] } } }).sort('channel').limit(20) return res or [] else: return g.db.tvstations.find_one({u'_id': ObjectId(zip_or_id)}) return []
def get_wiki_from_time(self, name, date, play_time): """由时间、日期获取Wiki,主要用于固定时间播放之节目""" # 兼容 Python 2.4 strptime 方法 date_to_time = time.strptime("%s %s" % (date, play_time), "%Y-%m-%d %H:%M") d = datetime(*date_to_time[:6]) #.strptime(date, "%Y-%m-%d") week_day = d.weekday() # Python中星期一为0 week_day = week_day + 1 # 时间范围冗余上下各10分钟 #play_time = time.strptime(play_time, "%H:%M") s_time = (d - timedelta(minutes=10)).strftime("%H:%M") e_time = (d + timedelta(minutes=10)).strftime("%H:%M") television = self.mongo_television.find({ "channel_code": self.channel_code, "week_day": str(week_day), "play_time": { "$gte": s_time, "$lte": e_time } }) for t in television: wiki_title = t['wiki_title'] try: if not t['wiki_id']: continue name.index(wiki_title) wiki = self.mongo_wiki.find_one( {"_id": ObjectId(t['wiki_id'])}) return wiki except ValueError, e: pass
def wrap(self, value): ''' Validates that ``value`` is an ObjectId (or hex representation of one), then returns it ''' self.validate_wrap(value) if isinstance(value, str): return ObjectId(value) return value
def get_transaction_details(db, user, values_as_nums=False): #Get transactions from_transactions = [t for t in db.transactions.find({'from_user':user['_id']}).sort('timestamp', pymongo.ASCENDING)] to_transactions = [t for t in db.transactions.find({'to_user':user['_id']}).sort('timestamp', pymongo.ASCENDING)] #Get totals and balance total_from = sum([t['value'] for t in from_transactions]) total_to = sum([t['value'] for t in to_transactions]) balance = total_from-total_to #Put into a single sorted list, using clever merging transactions = [] totals = {} while from_transactions and to_transactions: if from_transactions[-1]['timestamp'] > to_transactions[-1]['timestamp']: trans = from_transactions.pop() totals = update_totals(totals, 'to', trans) else: trans = to_transactions.pop() totals = update_totals(totals, 'from', trans) transactions.append(format_transaction(db, trans)) if to_transactions: for t in to_transactions: totals = update_totals(totals, 'from', t) transactions.append(format_transaction(db, t)) else: for t in from_transactions: totals = update_totals(totals, 'to', t) transactions.append(format_transaction(db, t)) #Build up the totals into nice to handle lists people_owe_you = {} you_owe_people = {} for user_id, total in totals.iteritems(): total = round(total,2) user_id = ObjectId.url_decode(user_id) user = db.users.find_one({'_id': user_id}) if total > 0: if values_as_nums: val = total else: val = u'£%.2f' % total people_owe_you[user['username']] = [user, val] elif total < 0: if values_as_nums: val = abs(total) else: val = u'£%.2f' % abs(total) you_owe_people[user['username']] = [user, val] print you_owe_people return transactions, balance, people_owe_you, you_owe_people
def test_url(self): a = ObjectId("123456789012") self.assertEqual(a.url_encode(), "313233343536373839303132") self.assertEqual(a, ObjectId.url_decode("313233343536373839303132")) self.assertEqual(a.url_encode(), str(a)) b = ObjectId() encoded = b.url_encode() self.assertEqual(b, ObjectId.url_decode(encoded))
def test_legacy_string(self): a = ObjectId() self.assertEqual(a.url_encode(legacy=True), a.legacy_str().encode("hex")) self.assertNotEqual(str(a), a.legacy_str()) self.assertEqual(a, ObjectId.from_legacy_str(a.legacy_str()))
def adjust_id(query): """ We need to adjust input query who has '_id' as a string to ObjectId used in MongoDB. """ spec = query['spec'] if spec.has_key('_id'): val = spec['_id'] if isinstance(val, str): newval = ObjectId(val) spec['_id'] = newval elif isinstance(val, unicode): newval = ObjectId(unicode.encode(val)) spec['_id'] = newval elif isinstance(val, list): newval = [] for item in val: if isinstance(item, str): newval.append(ObjectId(item)) elif isinstance(item, unicode): newval.append(ObjectId(unicode.encode(item))) else: raise Exception('Wrong type for id, %s=%s' \ % (item, type(item))) spec['_id'] = newval query['spec'] = spec return query
def query(): start = int(request.args.get('pms_js_time')) /1000 start = datetime.datetime.utcfromtimestamp(start) #start -= datetime.timedelta(hours=4) end = start + datetime.timedelta(hours=1) start_id = ObjectId.from_datetime(start) end_id = ObjectId.from_datetime(end) args = flatten(request.args) del args['pms_js_time'] query = { '_id': { '$gte': ObjectId.from_datetime(start), '$lte': ObjectId.from_datetime(end), } } query.update(args) l = [] for event in events.find(query).sort('_id'): wrap_event(event) l.append(event) return jsonify(events=l)
def test_from_datetime(self): d = datetime.datetime.utcnow() d = d - datetime.timedelta(microseconds=d.microsecond) oid = ObjectId.from_datetime(d) self.assertEqual(d, oid.generation_time) self.assertEqual("0" * 16, str(oid)[8:])
from pymongo.objectid import ObjectId import datetime obj = get_instance() c = obj.create_cursor("tuokouerchu") c.drop_collection("emotion") import random k = 0 for i in ["高兴","郁闷","伤心","沮丧","饿","宅","无聊"]: obj = get_instance() c = obj.create_cursor("tuokouerchu") row = c.emotion.insert({"id":k,"name":random.choice(range(1,100))}) k+=1 timebinray = ObjectId.from_datetime( datetime.datetime.now() ) for row in c.emotion.find(): obj = get_instance() obj.create_cursor("tuokouerchu") print row obj.auto_incr_id("emotion",row['_id']) del obj for row in c.emotion.find(): print row
def test_url_legacy(self): a = ObjectId() self.assertNotEqual(a.url_encode(), a.url_encode(legacy=True)) self.assertEqual(a, ObjectId.url_decode(a.url_encode(legacy=True), legacy=True))