I have copied and editied the OrderFlowers Amazon Lex blueprint to ask for a person's first and last name. When testing the Lambda function, I get the correct response but when trying to invoke my intent in Lex I get a 424 error Failed Dependency in my broswer console, and my test bot reports "An error has occurred: Invalid Lambda Response: Received error response from Lambda: Unhandled". I have looked over the code a number of times and I cannot work out if it is a permission issue or, there is something wrong with the fulfillment. My code is below and thanks in advance.
import math
import dateutil.parser
import datetime
import time
import os
import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
def get_slots(intent_request):
return intent_request['currentIntent']['slots']
def elicit_slot(session_attributes, intent_name, slots, slot_to_elicit, message):
return {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'ElicitSlot',
'intentName': intent_name,
'slots': slots,
'slotToElicit': slot_to_elicit,
'message': message
}
}
def close(session_attributes, fulfillment_state, message):
response = {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'Close',
'fulfillmentState': fulfillment_state,
'message': message
}
}
return response
def delegate(session_attributes, slots):
return {
'sessionAttributes': session_attributes,
'dialogAction': {
'type': 'Delegate',
'slots': slots
}
}
def parse_int(n):
try:
return int(n)
except ValueError:
return float('nan')
def build_validation_result(is_valid, violated_slot, message_content):
if message_content is None:
return {
"isValid": is_valid,
"violatedSlot": violated_slot,
}
return {
'isValid': is_valid,
'violatedSlot': violated_slot,
'message': {'contentType': 'PlainText', 'content': message_content}
}
def validate_get_name(first_name, last_name):
first_name = ['john', 'ben']
if first_name is None and first_name not in first_name:
return build_validation_result(False,
'FirstName',
'Sorry please state your first name. ')
last_name = ['smith', 'doran']
if last_name is None and last_name not in last_name:
return build_validation_result (False,
'LastName',
'Sorry please state your last name. ')
return build_validation_result(True, None, None)
def get_name(intent_request):
first_name = get_slots(intent_request)["FirstName"]
last_name = get_slots(intent_request)["LastName"]
source = intent_request['invocationSource']
if source == 'DialogCodeHook':
slots = get_slots(intent_request)
validation_result = validate_get_name(first_name, last_name)
if not validation_result['isValid']:
slots[validation_result['violatedSlot']] = None
return elicit_slot(intent_request['sessionAttributes'],
intent_request['currentIntent']['name'],
slots,
validation_result['violatedSlot'],
validation_result['message'])
output_session_attributes = intent_request['sessionAttributes'] if intent_request['sessionAttributes'] is not None else {}
if get_name is not None:
return delegate(output_session_attributes, get_slots(intent_request))
return close(intent_request['sessionAttributes'],
'Fulfilled',
{'contentType': 'PlainText',
'content': 'Thanks, we have now preformed your intent'})
def dispatch(intent_request):
logger.debug('dispatch userId={}, intentName={}'.format(intent_request['userId'], intent_request['currentIntent']['name']))
intent_name = intent_request['currentIntent']['name']
if intent_name == 'GetName':
return get_name(intent_request)
raise Exception('Intent with name ' + intent_name + ' not supported')
def lambda_handler(event, context):
os.environ['TZ'] = 'America/New_York'
time.tzset()
logger.debug('event.bot.name={}'.format(event['bot']['name']))
return dispatch(event)
I tried to reproduce your error and the only situations when the error occured in my case were when I had some syntax errors like improper indentation. Go to function logs (either: go to https://console.aws.amazon.com/cloudwatch, click Logs on the left pane, choose the logs group corresponding to your lambda function, choose log stream having the time when you saw the error and look for some messages or open your lambda function code, go to Monitoring tab and click View logs in CloudWatch)
I saw that the code you shared here has wrong indentation (functions body should have one more tab). Does your code in lambda function editor look the same or the indentaions disappeared while pasting the code here?
Related
I've been trying to test my PUT method in the following APITestcase:
def test_story_delete(self):
c = APIRequestFactory
user = User.objects.get(username='test1')
payload = {'storyName': 'changetest'}
request = c.put(reverse('storyFunctions',args=[self.room.pk,self.story.pk]), format='json')
force_authenticate(request,user=user)
My URL:
path('room/<int:pk>/story/<int:idStory>/adm', APIHstory.as_view(),name='storyFunctions'),
And I'm keep receiving this error:
TypeError: put() missing 1 required positional argument: 'path'
I don't understand what is going on because i declared the path inside request. Can someone help me?
Edit: sharing the view that I'm testing
class APIstory(APIView):
permission_classes = [IsAuthenticated]
def put(self,request, pk, idStory):
data = self.request.data
pk = self.kwargs['pk']
id = self.kwargs['idStory']
name = data['storyName'].strip()
if name == "" or str.isspace(name) or len(name) < 4:
return Response({"error": "minimum of 4 words"}, status=400)
if PokerRoom.objects.filter(id=pk).exists():
session = PokerRoom.objects.filter(id=pk)
if session[0].status == 'Finished':
return Response({'error': 'Session already ended'}, status=400)
else:
session = PokerRoom(id=pk)
if Story.objects.filter(id=id, idRoom=session).exists():
if not Story.objects.filter(idRoom=session, storyName=name).exists():
for hist in Story.objects.filter(id=id, idRoom=session):
if hist.status == 'Pending':
if hist.storyName == name:
return Response({'error':'story with the same name'}, status=400)
hist.storyName = name
hist.save()
status = hist.status
body = {"id":id,"storyName":name,"status":status}
message_socket("STORY_UPDATE", pk, body)
return Response({'success': 'story {} edited, status is {}.'.format(hist.id,hist.status)})
else:
return Response({'error': 'story already ended'}, status= 400)
else:
return Response({'error': 'story with the same name'}, status= 400)
return Response({'error': 'session doesnt exists.'}, status=400)
else:
return Response({'error': 'session doesnt exists.'}, status=400)
Edit2: I was forgetting to put the body in my request, but now I'm getting the following error: TypeError: super(type, obj): obj must be an instance or subtype of type
Shouldn't you add the request body also in a put request?
Something like this?
request = c.put(reverse('storyFunctions', kwargs={'pk': self.room.pk, 'idStory': self.story.pk}), payload, format='json')
As per the docs
I have a test case that is returning the following error.
Traceback
Traceback (most recent call last):
File "/usr/lib/python3.7/unittest/mock.py", line 1255, in patched
return func(*args, **keywargs)
File "/dir/to/project/Anwser/qanda/tests.py", line 29, in test_elasticsearch_upsert_on_save
q.save()
File "/dir/to/project/Anwser/qanda/models.py", line 40, in save
elasticsearch.upsert(self)
File "/dir/to/project/Anwser/qanda/service/elasticsearch.py", line 54, in upsert
doc_type = question_dict['_type']
TypeError: 'method' object is not subscriptable
Here is the function that lives inside elasticsearch.py
def upsert(question_model):
client = get_client()
question_dict = question_model.as_elastic_search_dict
doc_type = question_dict['_type']
del question_dict['_id']
del question_dict['_type']
response = client.update(
settings.ES_IDENX,
question_dict,
id=question_model.id,
body={
'doc': doc_type,
'doc_as_upsert': True,
}
)
return response
As i have read other threads about similar issues, i came to a conclusion that the problem relies in __getItem(self)__ of the object that is calling the function.
Since the function should return a dictionary, it returns a method instead.
Here is the function inside of model.
def as_elastic_search_dict(self):
return {
'_id': self.id,
'_type': 'doc',
'text': '{}\n{}'.format(self.title, self.question),
'question_body': self.question,
'title': self.title,
'id': self.id,
'created': self.created,
}
TestCase:
class QuestionSaveTestCase(TestCase):
"""
Testing Question.save()
"""
#patch('qanda.service.elasticsearch.Elasticsearch')
def test_elasticsearch_upsert_on_save(self, ElasticSearchMock):
user = User.objects.create(
username='unittest',
password='unittest'
)
question_title = 'Unit test'
question_body = 'Some unit test'
q = Question(title=question_title,
question=question_body,
user=user)
q.save()
self.assertIsNotNone(q.id)
self.assertTrue(ElasticSearchMock.called)
mock_client = ElasticSearchMock.return_value
mock_client.update.assert_called_once_with(
settings.ES_IDENX,
id=q.id,
body={
'doc': {
'_type': 'doc',
'text': '{}\n{}'.format(question_title, question_body),
'question_body': question_body,
'title': question_title,
'id': q.id,
'created': q.created,
},
'doc_as_upsert': True,
}
)
What are all the possible usecase's that can be used to solve this problem? If my understanding was correct, then i should override __getItem(self)__ to return the dictionary. If that is correct how should i implement __getItem(self)__ and if it will be configured to return the dictionary, how will it affect the object lifecycle in total?
you need to execute the method, you are missing the parenthesis after the method name, change question_model.as_elastic_search_dict to question_model.as_elastic_search_dict().
So your function will be:
def upsert(question_model):
client = get_client()
question_dict = question_model.as_elastic_search_dict()
doc_type = question_dict['_type']
del question_dict['_id']
del question_dict['_type']
response = client.update(
settings.ES_IDENX,
question_dict,
id=question_model.id,
body={
'doc': doc_type,
'doc_as_upsert': True,
}
)
return response
I try to link django API-REST with a form that has an associated model. Everything works well until I do the:
return response.Response (serializer.data, status = status.HTTP_201_CREATED)
JavaScript
// To Save the Suggestion
let ajax_suggestion_save = function (type, url, data, context) {
let name_dm = $('#name-db-saved').val();
$.ajax({
type: type,
url: url,
data: data,
context: context,
beforeSend: function (xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
},
success: function (response) {
$.niftyNoty({
type: "success",
container: 'floating',
title: 'Your information was saved successfully.',
message: 'We much appreciate your interest of contact us, part of the growth of this platform it is base on your collaboration through your ideas.',
closeBtn: true,
timer: 4000
});
},
error: function (response) {
if (Object.keys(response.responseJSON).length >= 1) {
$.each(response.responseJSON, function (key, value) {
$.niftyNoty({
type: 'danger',
container: 'floating',
title: 'Ups, apparently we have problems saving your information.',
message: 'Please check the following ' +
'Error in <strong> ' + key + ' </strong>, with the following error <strong> ' + value + ' </strong>.',
closeBtn: true,
timer: 4000
});
});
} else {
$.niftyNoty({
type: 'danger',
container: 'floating',
title: 'Ups, apparently we have problems saving your information.',
message: 'Ups, apparently we have problems saving your suggestion. ' +
'If the problem persists, notify the system administrator in the help section.' +
'You suggestion <strong> ' + name_dm + ' </strong> not will be saved.',
closeBtn: true,
timer: 4000
});
}
}
});
};
$('#contactus').on('click', function (type, url, data, context) {
ajax_suggestion_save('POST', '/miscellaneous/api/contactus/create/', $("#contactus_form").serializeArray(), this);
});
Model
class DimContactUs(Model):
class Meta:
order_with_respect_to = 'email'
verbose_name = 'Contact'
verbose_name_plural = 'Contact'
id_contact_us = UUIDField(primary_key=True, default=uuid.uuid4, editable=False,
help_text='Universally unique identifier of a Contact')
name = CharField(max_length=100, help_text='Name of the Contact')
email = EmailField(max_length=70, help_text='Email of these Contact')
# id_user = ForeignKey(User, on_delete=CASCADE, help_text='Foreign Key of the User that made this Contact')
title = CharField(max_length=100, help_text='Title of the Contact')
message = TextField(
help_text='Short description of this Contact, e.g. : We want to include ...!')
url = URLField(null=True, blank=True,
help_text='Please copy the url associated to this Contact')
active = BooleanField(default=True, help_text='Do you want to make public this Contact?')
time_create = DateTimeField(auto_now=True, auto_now_add=False, editable=False, help_text='Time it was created')
time_stamp = DateField(auto_now=True, auto_now_add=False, help_text='Time of last modification')
def __str__(self):
return self.title
Serializers
class DimContactUsSer(serializers.ModelSerializer):
class Meta:
model = DimContactUs
fields = '__all__'
View
class ContactUsCreate(CreateAPIView):
queryset = DimContactUs.objects.all()
serializer_class = DimContactUsSer
#csrf_exempt
def post(self, request, *args, **kwargs):
try:
if request.method == 'POST':
form = DimContactUsForm(request.POST, request.FILES)
serializer = DimSuggestionSer(data=request.data)
if form.is_valid() and serializer.is_valid():
serializer.save()
return response.Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return response.Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
except Exception as exception:
return response.Response(exception.args, status=status.HTTP_400_BAD_REQUEST)
Here, the response sends me to the REST API page instead of staying in the current one.
I would expect your missing the import statement for the module, I cannot see your import statements.
from rest_framework import status
I got an exception when i create a sms to send
here is my functions
def send_sms(to_number, body):
account_sid = settings.TWILIO_ACCOUNT_SID
auth_token = settings.TWILIO_AUTH_TOKEN
twilio_number = '+15005550006'
client = TwilioRestClient(account_sid, auth_token)
try :
client.messages.create(to=to_number,
from_=twilio_number,
body=body)
except Exception as e:
print e.message
def generate_code():
return str(random.randrange(100000, 999999))
def send_confirmation_code(request,to_number):
verification_code = generate_code()
send_sms(to_number, verification_code)
request.session['verification_code'] = verification_code
return verification_code
I'm using flask-jwt and flask-restful
This is how flask-jwt handling errors(taken from its github repo) but none of them let me take the parameters of JWTError.
if auth is None:
raise JWTError('Authorization Required', 'Authorization header was missing', 401, {
'WWW-Authenticate': 'JWT realm="%s"' % realm
})
parts = auth.split()
if parts[0].lower() != auth_header_prefix.lower():
raise JWTError('Invalid JWT header', 'Unsupported authorization type')
elif len(parts) == 1:
raise JWTError('Invalid JWT header', 'Token missing')
elif len(parts) > 2:
raise JWTError('Invalid JWT header', 'Token contains spaces')
try:
handler = _jwt.decode_callback
payload = handler(parts[1])
except SignatureExpired:
raise JWTError('Expired JWT', 'Token is expired', 401, {
"WWW-Authenticate": 'JWT realm="{0}"'.format(realm)
})
except BadSignature:
raise JWTError('Invalid JWT', 'Token is undecipherable')
_request_ctx_stack.top.current_user = user = _jwt.user_callback(payload)
if user is None:
raise JWTError('Invalid JWT', 'User does not exist')
And the following are the different ways how I try to handle JWTError
In flask:
def handle_user_exception_again(e):
if isinstance(e, JWTError):
data = {'status_code': 1132, 'message': "JWTError already exists."}
return jsonify(data), e.status_code, e.headers
return e
app.handle_user_exception = handle_user_exception_again
In flask-restful (handle_error)
class FlaskRestfulJwtAPI(Api):
def handle_error(self, e):
if isinstance(e, JWTError):
code = 400
data = {'status_code': code, 'message': "JWTError already exists."}
elif isinstance(e, KeyError):
code = 400
data = {'status_code': code, 'message': "KeyError already exists."}
else:
# Did not match a custom exception, continue normally
return super(FlaskRestfulJwtAPI, self).handle_error(e)
return self.make_response(data, code)
In flask-restful (error_router)
class FlaskRestfulJwtAPI(Api):
def error_router(self, original_handler, e):
print(type(e))
if e is JWTError:#KeyError:
data = {
"code":400,
"message":"JWTError"
}
return jsonify(data), 400
elif isinstance(e,KeyError):
data = {
"code":400,
"message":"KeyError"
}
return jsonify(data), 400
else:
return super(FlaskRestfulJwtAPI, self).error_router(original_handler, e)
I see that you are trying to raise an HTTPException from these errors, which helps with returning them to users. To raise an HTTP exception, you can catch all errors and if they are an instance of a JWTError, you can convert them to an instance of an HTTPException using a function like the following:
def convert_to_http_exception(e):
if isinstance(e, JWTError):
jwtdescription = e.error + ": " + e.description
http_exception = HTTPException(description=jwtdescription)
http_exception.code = e.status_code
return http_exception
else:
return e