From c7a4d6e54e456e7498e289dbdbb1709f1b38e1f5 Mon Sep 17 00:00:00 2001 From: Doug Black Date: Fri, 30 Jun 2017 10:43:39 -0700 Subject: [PATCH 1/2] Support nesting TwiML verbs via `with` --- tests/unit/twiml/test_messaging_response.py | 14 ++++++++++++- tests/unit/twiml/test_voice_response.py | 23 ++++++++++++++++----- twilio/twiml/__init__.py | 2 +- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/tests/unit/twiml/test_messaging_response.py b/tests/unit/twiml/test_messaging_response.py index 014742704e..bc9d9efb09 100644 --- a/tests/unit/twiml/test_messaging_response.py +++ b/tests/unit/twiml/test_messaging_response.py @@ -23,13 +23,25 @@ def test_response(self): ) def test_response_chain(self): - r = MessagingResponse().message('Hello').redirect(url='example.com') + with MessagingResponse() as r: + r.message('Hello') + r.redirect(url='example.com') assert_equal( self.strip(r), 'Helloexample.com' ) + def test_nested_verbs(self): + with MessagingResponse() as r: + with r.message('Hello') as m: + m.media('example.com') + + assert_equal( + self.strip(r), + 'Helloexample.com' + ) + class TestMessage(TwilioTest): diff --git a/tests/unit/twiml/test_voice_response.py b/tests/unit/twiml/test_voice_response.py index 2d2d259ec1..2a30cd6ab0 100644 --- a/tests/unit/twiml/test_voice_response.py +++ b/tests/unit/twiml/test_voice_response.py @@ -30,17 +30,30 @@ def test_response(self): ) def test_response_chain(self): - r = VoiceResponse().hangup().leave().sms( - 'twilio sms', - to='+11234567890', - from_='+10987654321' - ) + with VoiceResponse() as r: + r.hangup() + r.leave() + r.sms( + 'twilio sms', + to='+11234567890', + from_='+10987654321' + ) assert_equal( self.strip(r), 'twilio sms' ) + def test_nested_verbs(self): + with VoiceResponse() as r: + with r.gather() as g: + g.say('Hello', voice='man') + + assert_equal( + self.strip(r), + 'Hello' + ) + class TestSay(TwilioTest): diff --git a/twilio/twiml/__init__.py b/twilio/twiml/__init__.py index 8e17325c7f..12932af2b3 100644 --- a/twilio/twiml/__init__.py +++ b/twilio/twiml/__init__.py @@ -80,7 +80,7 @@ def append(self, verb): raise TwiMLException('Only appending of TwiML is allowed') self.verbs.append(verb) - return self + return verb def xml(self): """ From 97ec763056086db6d13279fd2d7e1c8e638bf101 Mon Sep 17 00:00:00 2001 From: Doug Black Date: Fri, 30 Jun 2017 11:32:13 -0700 Subject: [PATCH 2/2] Introduce `nest()` to preserve `append()` behavior --- twilio/twiml/__init__.py | 13 ++++++++- twilio/twiml/messaging_response.py | 8 +++--- twilio/twiml/voice_response.py | 46 +++++++++++++++--------------- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/twilio/twiml/__init__.py b/twilio/twiml/__init__.py index 12932af2b3..07c898ec0e 100644 --- a/twilio/twiml/__init__.py +++ b/twilio/twiml/__init__.py @@ -74,12 +74,23 @@ def append(self, verb): """ Add a TwiML doc :param verb: TwiML Document - :return: + :return: self """ if not isinstance(verb, TwiML): raise TwiMLException('Only appending of TwiML is allowed') self.verbs.append(verb) + return self + + def nest(self, verb): + """ + Add a TwiML doc. Unlike `append()`, this returns the created verb. + :param verb: TwiML verb + :return: the TwiML verb + """ + if not isinstance(verb, TwiML): + raise TwiMLException('Only nesting of TwiML is allowed') + self.verbs.append(verb) return verb def xml(self): diff --git a/twilio/twiml/messaging_response.py b/twilio/twiml/messaging_response.py index a4adcc7310..08de32d989 100644 --- a/twilio/twiml/messaging_response.py +++ b/twilio/twiml/messaging_response.py @@ -32,7 +32,7 @@ def message(self, :param kwargs: other attributes :return: element """ - return self.append(Message( + return self.nest(Message( body=body, to=to, from_=from_, @@ -51,7 +51,7 @@ def redirect(self, url, method=None, **kwargs): :param kwargs: other attributes :return: element """ - return self.append(Redirect( + return self.nest(Redirect( method=method, url=url, **kwargs @@ -80,7 +80,7 @@ def body(self, body): :param body: body of message :return: element """ - return self.append(Body(body)) + return self.nest(Body(body)) def media(self, url): """ @@ -89,7 +89,7 @@ def media(self, url): :param url: media URL :return: element """ - return self.append(Media(url)) + return self.nest(Media(url)) class Body(TwiML): diff --git a/twilio/twiml/voice_response.py b/twilio/twiml/voice_response.py index 1ebf36ae96..2419a97fc4 100644 --- a/twilio/twiml/voice_response.py +++ b/twilio/twiml/voice_response.py @@ -45,7 +45,7 @@ def dial(self, :param kwargs: additional attributes :return: element """ - return self.append(Dial( + return self.nest(Dial( number=number, action=action, method=method, @@ -67,7 +67,7 @@ def echo(self, :return: element """ - return self.append(Echo( + return self.nest(Echo( **kwargs )) @@ -91,7 +91,7 @@ def enqueue(self, :param kwargs: additional attributes :return: element """ - return self.append(Enqueue( + return self.nest(Enqueue( name, action=action, method=method, @@ -133,7 +133,7 @@ def gather(self, :param kwargs: additional attributes :return: element """ - return self.append(Gather( + return self.nest(Gather( action=action, method=method, timeout=timeout, @@ -155,7 +155,7 @@ def hangup(self): :return: element """ - return self.append(Hangup()) + return self.nest(Hangup()) def leave(self): """ @@ -163,7 +163,7 @@ def leave(self): :return: element """ - return self.append(Leave()) + return self.nest(Leave()) def pause(self, length=None): """ @@ -172,7 +172,7 @@ def pause(self, length=None): :param length: time in seconds to pause :return: element """ - return self.append(Pause(length=length)) + return self.nest(Pause(length=length)) def play(self, url=None, @@ -188,7 +188,7 @@ def play(self, :param kwargs: additional attributes :return: element """ - return self.append(Play( + return self.nest(Play( url=url, loop=loop, digits=digits, @@ -225,7 +225,7 @@ def record(self, :param kwargs: additional attributes :return: element """ - return self.append(Record( + return self.nest(Record( action=action, method=method, timeout=timeout, @@ -249,7 +249,7 @@ def redirect(self, url, method=None, **kwargs): :param kwargs: additional attributes :return: element """ - return self.append(Redirect(url, method=method, **kwargs)) + return self.nest(Redirect(url, method=method, **kwargs)) def reject(self, reason=None, **kwargs): """ @@ -259,7 +259,7 @@ def reject(self, reason=None, **kwargs): :param kwargs: additional attributes :return: element """ - return self.append(Reject(reason=reason, **kwargs)) + return self.nest(Reject(reason=reason, **kwargs)) def say(self, body, @@ -277,7 +277,7 @@ def say(self, :param kwargs: additional attributes :return: element """ - return self.append(Say( + return self.nest(Say( body, loop=loop, language=language, @@ -305,7 +305,7 @@ def sms(self, :param kwargs: additional attributes :return: element """ - return self.append(Sms( + return self.nest(Sms( body, to=to, from_=from_, @@ -351,7 +351,7 @@ def client(self, :param kwargs: additional attributes :return: element """ - return self.append(Client( + return self.nest(Client( name, method=method, url=url, @@ -401,7 +401,7 @@ def conference(self, :param kwargs: additional attributes :return: element """ - return self.append(Conference( + return self.nest(Conference( name, muted=muted, start_conference_on_enter=start_conference_on_enter, @@ -443,7 +443,7 @@ def number(self, :param kwargs: additional attributes :return: element """ - return self.append(Number( + return self.nest(Number( number, send_digits=send_digits, url=url, @@ -472,7 +472,7 @@ def queue(self, :param kwargs: additional attributes :return: element """ - return self.append(Queue( + return self.nest(Queue( queue_name, url=url, method=method, @@ -490,7 +490,7 @@ def sim(self, :param sid: sim sid :return: element """ - return self.append(Sim( + return self.nest(Sim( sid, **kwargs )) @@ -519,7 +519,7 @@ def sip(self, :param kwargs: additional attributes :return: element """ - return self.append(Sip( + return self.nest(Sip( uri, username=username, password=password, @@ -653,7 +653,7 @@ def task(self, attributes, **kwargs): :param attributes: Attributes for a task :return: element """ - return self.append(Task(attributes, **kwargs)) + return self.nest(Task(attributes, **kwargs)) class Task(TwiML): @@ -700,7 +700,7 @@ def say(self, :param kwargs: additional attributes :return: element """ - return self.append(Say( + return self.nest(Say( body, loop=loop, language=language, @@ -722,7 +722,7 @@ def play(self, :param kwargs: additional attributes :return: element """ - return self.append(Play( + return self.nest(Play( url=url, loop=loop, digits=digits, @@ -736,7 +736,7 @@ def pause(self, length=None): :param length: time to pause :return: element """ - return self.append(Pause(length=length)) + return self.nest(Pause(length=length)) class Pause(TwiML):