Support dictionary-style narrows in back end API.

(We continue to support tuple-style narrows as well.)

(imported from commit 0154c1cba7503471b112ce22f280b619133e0211)
This commit is contained in:
Steve Howell 2014-02-10 18:31:26 -05:00
parent 5b920a5226
commit ea8d9efa00
2 changed files with 47 additions and 21 deletions

View File

@ -602,7 +602,18 @@ class GetOldMessagesTest(AuthedTestCase):
messages.
"""
self.login("hamlet@zulip.com")
self.check_well_formed_messages_response(self.post_with_params({}))
result = self.post_with_params(dict())
self.check_well_formed_messages_response(result)
# We have to support the legacy tuple style while there are old
# clients around, which might include third party home-grown bots.
narrow = [['pm-with', 'othello@zulip.com']]
result = self.post_with_params(dict(narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
narrow = [dict(operator='pm-with', operand='othello@zulip.com')]
result = self.post_with_params(dict(narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
def test_get_old_messages_with_narrow_pm_with(self):
"""
@ -623,8 +634,8 @@ class GetOldMessagesTest(AuthedTestCase):
emails = dr_emails(get_display_recipient(personals[0].recipient))
self.login(me)
result = self.post_with_params({"narrow": ujson.dumps(
[['pm-with', emails]])})
narrow = [dict(operator='pm-with', operand=emails)]
result = self.post_with_params(dict(narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
for message in result["messages"]:
@ -650,8 +661,8 @@ class GetOldMessagesTest(AuthedTestCase):
stream_name = get_display_recipient(stream_messages[0].recipient)
stream_id = stream_messages[0].recipient.id
result = self.post_with_params({"narrow": ujson.dumps(
[['stream', stream_name]])})
narrow = [dict(operator='stream', operand=stream_name)]
result = self.post_with_params(dict(narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
for message in result["messages"]:
@ -679,8 +690,8 @@ class GetOldMessagesTest(AuthedTestCase):
self.send_message("starnine@mit.edu", u"\u03bb-stream", Recipient.STREAM)
self.send_message("starnine@mit.edu", u"\u03bb-stream.d", Recipient.STREAM)
result = self.post_with_params({"num_after": 2, "narrow": ujson.dumps(
[['stream', u'\u03bb-stream']])})
narrow = [dict(operator='stream', operand=u'\u03bb-stream')]
result = self.post_with_params(dict(num_after=2, narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
messages = get_user_messages(get_user_profile_by_email("starnine@mit.edu"))
@ -712,8 +723,8 @@ class GetOldMessagesTest(AuthedTestCase):
self.send_message("starnine@mit.edu", "Scotland", Recipient.STREAM,
subject=u"\u03bb-topic.d")
result = self.post_with_params({"num_after": 2, "narrow": ujson.dumps(
[['topic', u'\u03bb-topic']])})
narrow = [dict(operator='topic', operand=u'\u03bb-topic')]
result = self.post_with_params(dict(num_after=2, narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
messages = get_user_messages(get_user_profile_by_email("starnine@mit.edu"))
@ -739,8 +750,8 @@ class GetOldMessagesTest(AuthedTestCase):
self.send_message("othello@zulip.com", "hamlet@zulip.com", Recipient.PERSONAL)
self.send_message("iago@zulip.com", "Scotland", Recipient.STREAM)
result = self.post_with_params({"narrow": ujson.dumps(
[['sender', "othello@zulip.com"]])})
narrow = [dict(operator='sender', operand='othello@zulip.com')]
result = self.post_with_params(dict(narrow=ujson.dumps(narrow)))
self.check_well_formed_messages_response(result)
for message in result["messages"]:
@ -819,8 +830,8 @@ class GetOldMessagesTest(AuthedTestCase):
"""
self.login("hamlet@zulip.com")
for operator in ['', 'foo', 'stream:verona', '__init__']:
params = dict(anchor=0, num_before=0, num_after=0,
narrow=ujson.dumps([[operator, '']]))
narrow = [dict(operator=operator, operand='')]
params = dict(anchor=0, num_before=0, num_after=0, narrow=ujson.dumps(narrow))
result = self.client.post("/json/get_old_messages", params)
self.assert_json_error_contains(result,
"Invalid narrow operator: unknown operator")

View File

@ -19,7 +19,7 @@ from zerver.lib.cache import generic_bulk_cached_fetch
from zerver.lib.query import last_n
from zerver.lib.response import json_success, json_error
from zerver.lib.utils import statsd
from zerver.lib.validator import check_list, check_int
from zerver.lib.validator import check_list, check_int, check_dict, check_string
from zerver.models import Message, UserProfile, Stream, \
Recipient, UserMessage, bulk_get_recipients, get_recipient, \
get_user_profile_by_email, get_stream, valid_stream_name, \
@ -278,13 +278,28 @@ def narrow_parameter(json):
raise ValueError("argument is not a list")
def convert_term(elem):
if not isinstance(elem, list):
raise ValueError("element is not a list")
if (len(elem) != 2
or any(not isinstance(x, str) and not isinstance(x, unicode)
for x in elem)):
raise ValueError("element is not a string pair")
return dict(operator=elem[0], operand=elem[1])
# We have to support a legacy tuple format.
if isinstance(elem, list):
if (len(elem) != 2
or any(not isinstance(x, str) and not isinstance(x, unicode)
for x in elem)):
raise ValueError("element is not a string pair")
return dict(operator=elem[0], operand=elem[1])
if isinstance(elem, dict):
validator = check_dict([
('operator', check_string),
('operand', check_string),
])
error = validator('elem', elem)
if error:
raise JsonableError(error)
# whitelist the fields we care about for now
return dict(operator=elem['operator'], operand=elem['operand'])
raise ValueError("element is not a dictionary")
return map(convert_term, data)