I have proto message that I need to attach a string containing information about the data (units, scaling factor etc).
I am using custom options as per the proto2 guide. I also have attempted to follow a previous question where they printed custom options for 1 message here. I would like to print out all fields from the message along side the string. I have been struggling to find a solution, so far what i have tried is:
In my .proto file: The Service message contains fields that are themselves messages such as My_Message.
import "google/protobuf/descriptor.proto";
extend google.protobuf.FieldOptions {
optional string formatting_stuff = 50000;
}
message My_Message
{
optional uint32 base_frequency_hz = 1 [(formatting_stuff) = "test"];
optional float trigger_frequency_hz = 2 [(formatting_stuff) = "test2"];
...
}
message Service
{
optional My_Message x = 13;
...
}
Then in the python file,how would iterate over each field in Service and the nested message My_Message to retrieve both its value and also then extract the 'formatting_stuff'.
This is my attempt, but I can not get the field options to print the custom options:
messanger.py
...
rsp = self.proto.Service().FromString(self.data)
desc = protobuf_file.Service.My_Message.DESCRIPTOR
for rsp_field in response.DESCRIPTOR.fields:
print("Response Field name: ", rsp_field.name)
print("Response Field value: ", getattr(rsp, rsp_field.name))
options = desc.GetOptions()
formatting = options.Extensions[protobuf_file.formatting_stuff]
print("Response Field formatting: ", formatting)
The terminal output is:
Response Field name: base_frequency_hz
Response Field value: 720000
Response Field formatting:
Response Field name: trigger_frequency_hz
Response Field value: 3000.0
Response Field formatting:
As you can see, my custom fields are not being printed. Please could you assist me with printing out the custom options.
Kind regards
Related
def generate_waybill(shipper, consignee, services, profile):
success = True
request = {
"Shipper": shipper,
"Consignee": consignee,
"Services": services
}
client = Client(url)
res = client.service.GenerateWayBill(Request=request, Profile=profile)
print("RESPONSE GENERATE WAYBILL: \n\n", res, res.json())
if not res:
success = False
return res, success
While calling the generate_waybill function i get an execption from zeep >>> 'Invalid enum value 'ProductType.Dutiables'
In the services object it has a key named as ProductType and its Data Type ProductType [Enumerator] and the allowed values for this fields are ProductType.Docs, ProductType.Dutiables.
The services object
services = {
"ProductCode": shipping_options['bluedart']['product_code'],
"ProductType": shipping_options['bluedart']['product_type'],
"PieceCount": return_request_line_items.all().count(),
"ActualWeight": weight,
"CreditReferenceNo": reference_id,
"PickupDate": timezone.now() + timezone.timedelta(days=2),
"PickupTime": '1052',
"RegisterPickup": True,
"IsReversePickup": True
}
In the "ProductType": field I have passed hard coded string value as 'ProductType.Dutiables'
I have also tried creating a calss with Enum type like
from enum import Enum
class ProductType(Enum):
Dutiables = "Dutiables"
and used this as ProductType.Dutiables in the 'ProductType' field.
But nothing seems to work for me. Please help!
zeep.exceptions.Fault: The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:Request. The InnerException message was 'Invalid enum value 'ProductType.Dutiables' cannot be deserialized into type 'SAPI.Entities.Enums.AWBGeneration.ProductType'. Ensure that the necessary enum values are present and are marked with EnumMemberAttribute attribute if the type has DataContractAttribute attribute.'. Please see InnerException for more details.
I can't find a solution because the lack of understanding of programming.
I have created multiple Python Scripts where I do API calls to get results, the results are converted to JSON.
I want to store two specific fields from the JSON result for each user in an array, so I then later can make a "search" based of a users input(field), match it to the array and send a post request later.
The fields I want is: 'email' and 'userid', so when I search for the input (email) I can retrieve the userid, and send the post call from a button click.
So I understand that I can retrieve either email or userid by using the teo first lines to print the values. But the issue is when i try to store it in the array:
users = response.json()
print(users['user'][1]['userid']) #get user id
print(users['user'][1]['email']) #get email
json_length = len(users['user']) #get amount of users
print(json_length)
user_list = []
for i in users:
user_details = {"id":None, "email":None}
user_details['id'] = users['userid'][i]
user_details['email'] = users['email'][i]
user_list.append(user_details)
print(user_list)
I get the following error:
Exception has occurred: TypeError list indices must be integers or
slices, not str
File "C:...test2.py",
line 32, in
user_details['id'] = users['user'][i]['userid']
The JSON (multiple fields are removed and renamed)
{
"total":"2001",
"totalcount":"2",
"user":[
{
"userid":1,
"name":{
"firstname":"John",
"lastname":"Doe (Inactive)"
},
"email":"j.doe#something.com",
"status":"Inactive",
"organisation":{
"orgname":"something",
"orgid":1
},
},
{
"userid":2,
"name":{
"firstname":"Emma",
"lastname":"Hart (Inactive)"
},
"email":"e.hart#otherthing.com",
"status":"Inactive",
"organisation":{
"orgname":"otherthing",
"orgid":2
},
}
]
}
Any help for pointing what I'm doing wrong or help?
You're looping over the full JSON response keys, not the actual users list, then i would be each user object, so use that rather than the response again
Try
for i in users.get('user', []):
...
user_details['id'] = i['userid']
user_details['email'] = i['email']
You can also build that list in one line
user_list = [ {"id":u["userid"], "email":u["email"]} for u in users.get('user', []) ]
print(user_list)
I have the following json:
{
"email": "lalalalal#gmail.com"
}
and little test script:
file = open('/Users/user/PycharmProjects/Test/newfile.json')
x = json.load(file)
y = repr(x['email'])
print('My test email is ' + y)
I receive next output:
My test email is 'lalalalal#gmail.com'
My question is:
How to receive JSON value data (print also) without ordinary quotes in output?
To receive:
My test email is lalalalal#gmail.com
You should not use repr. You can get the value without repr
x['email']
I tried looking around for an answer and gave it a great many tries, but there's something strange going on here. I got some functions in my view that operate on JSON data that comes in via AJAX. Currently I'm trying to do some unit testing on these.
In my test case I have:
kwargs = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
url = '/<correct_url>/upload/'
data = {
"id" : p.id
}
c = Client()
response = c.delete(url, data, **kwargs)
content_unicode = response.content.decode('utf-8')
content = json.loads(content_unicode)
p.id is just an integer that comes from a model I'm using.
I then have a function that is being tested, parts of which looks like follows:
def delete_ajax(self, request, *args, **kwargs):
print (request.body)
body_unicode = request.body.decode('utf-8')
print (body_unicode)
body_json = json.loads(body_unicode)
The first print statement yields:
.....b"{'id': 1}"
The other one:
{'id': 1}
and finally I get an error for fourth line as follows:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)
What's going wrong here? I understand that correct JSON format should be {"id": 1} and that's what I'm sending from my test case. But somewhere along the way single-quotes are introduced into the mix causing me head ache.
Any thoughts?
You need to pass a json string to Client.delete(), not a Python dict:
kwargs = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'}
url = '/<correct_url>/upload/'
data = json.dumps({
"id" : p.id
})
c = Client()
response = c.delete(url, data, **kwargs)
You should also set the content-type header to "application/json" and check the content-type header in your view but that's another topic.
I'm building a website using Django. And I want that users can be able to receive alerts via SMS when new topics are posted.
I tested textlocal but I had an issue when trying to send SMS to multiple numbers (numbers = ['xxxxx','xxxxx']) .(I don't want to use group_id).
Generally I want to be able to do something like this:
numbers = (SELECT number FROM users WHERE SMS_subscribe=1)
sender = 'mywebsite'
message = 'Hey, a new topic was posted'
send_sms(numbers, message, sender)
My textlocal test code:
#!/user/bin/python
# -*- coding: utf-8 -*-
from urllib2 import Request, urlopen
from urllib import urlencode
def send_sms(uname, hash_code, numbers, message, sender):
data = urlencode({
'username' : uname,
'hash' : hash_code,
'numbers' : numbers,
'message' : message,
'sender' : sender,
'test' : True
})
#data = data.encode('utf-8')
request = Request('https://api.txtlocal.com/send/?')
response = urlopen(request, data)
return response.read()
def just_one_sms_message(message, annonce_link, sender):
links_len=len(annonce_link) + len(sender) + 1
sms_max_len = 160 - links_len
if len(message)>sms_max_len:
message = message[:sms_max_len-6]+'... : '
else:
message += ' : '
return message + annonce_link + '\n' + sender
username = 'xxxxxxx#gmail.com'
hash_code = '3b5xxxxxxxxxxxxxxxxxxxxxxxxxxx8d83818'
numbers = ('2126xxxxx096','2126xxxxx888')
annonce_link = 'http://example.com/'
sender = 'sender'
message = 'New topics..'
message = just_one_sms_message(message, annonce_link, sender)
resp = send_sms(username, hash_code, numbers, message, sender)
print resp
Executing this code I get this error :
{"warnings":[{"code":3,"message":"Invalid number"}],"errors":[{"code":4,"message":"No recipients specified"}],"status":"failure"}
But if I change: numbers=('2126xxxxx096')it works.
What is the best way or web service to do this ?
There are a couple issues you're running into. The first is how tuple literals are defined.
('somenumber') is equivalent to 'somenumber' in python. It's just a string. The parentheses alone do not define a tuple literal. To define a single-element tuple literal, you need a trailing comma of the first element. E.G. ('somenumber',).
The second issue is how urlencode works. For each value in the data dictionary, it asks for the string representation.
In the case of ('2126xxxxx096','2126xxxxx888'), since it's evaluated as a tuple, it's encoded as ('2126xxxxx096','2126xxxxx888'), resulting in %28%272126xxxxx096%27%2C+%272126xxxxx888%27%29.
In the case of ('2126xxxxx096'), since it's evaluated as a string, it's encoded as 2126xxxxx096. Notice the lack of junk characters like %28 and %29.
So, in short, since the value of numbers in the urlencode dictionary is a tuple when you have multiple numbers, you need to convert the tuple into a comma-separated string. This can be accomplished via ",".join(numbers), which in the case of ('2126xxxxx096','2126xxxxx888') produces 2126xxxxx096%2C2126xxxxx888. With the fixed encoding, your message should now send to multiple numbers.