How to view c-message from azure service queue in Python - python

I am using Azure service bus to view message contents of a messages sent from an service bus service.
I am using the message.get_message() command and it returns a c message as specified in the documentation
https://learn.microsoft.com/en-us/python/api/uamqp/uamqp.message.message?view=azure-python
Is there a way to view the contents of the c message?
<uamqp.c_uamqp.cMessage object at 0x0000000003180F50>

What do you mean about the contents of the c message?
I think the content of the c message you received is the date to send in the message. So according to the offical API reference Message class, you should use message.get_data() to get the body of the message to view its content, as the figure below.
Or just only to view it by print(...) like the sample code azure-uamqp-python/samples/sample_uamqp_receive_simple.py.
message = uamqp.receive_message(uri, auth=plain_auth)
print("Received: {}".format(message))
If your real intention is to parse the uamqp.c_uamqp.cMessage data structure of the massage to view the internal contents, you can refer to the SO thread Parsing C Structs in Python with the source codes message.h & message.c of Azure/azure-uamqp-c and the Python wrapper code message.pyx to try to parse it.
After I reviewed them above, the core data structure of uamqp.c_uamqp.cMessage is as below.
typedef struct MESSAGE_INSTANCE_TAG
{
BODY_AMQP_DATA* body_amqp_data_items;
size_t body_amqp_data_count;
AMQP_VALUE* body_amqp_sequence_items;
size_t body_amqp_sequence_count;
AMQP_VALUE body_amqp_value;
HEADER_HANDLE header;
delivery_annotations delivery_annotations;
message_annotations message_annotations;
PROPERTIES_HANDLE properties;
application_properties application_properties;
annotations footer;
uint32_t message_format;
} MESSAGE_INSTANCE;
Hope it helps.

Related

Cannot deserialize protobuf binary (created by Nodejs) in Python

Please review below context and help resolve the issue
I define below message in device.proto
message DeviceConfiguration {
message Resolution {
uint32 width = 1;
uint32 height = 2;
}
string device_name = 1;
string brand_name = 2;
Resolution resolution = 3;
}
Then, compile this message into 2 languages: Nodejs (device_pb.js) and Python(device_pb2.py)
1. From Nodejs: send above message to Kafka
const {DeviceConfiguration} = require("./device_pb")
const resolution = new DeviceConfiguration.Resolution();
resolution.setWidth(1280);
resolution.setHeight(960);
const deviceConfiguration = new DeviceConfiguration();
deviceConfiguration.setDeviceName("S6");
deviceConfiguration.setBrandName("samsung");
deviceConfiguration.setResolution(resolution);
let binaryEvent = deviceConfiguration.serializeBinary();
Finally, use Kafka-node to send binaryEvent value to a Kafka topic
2. From Python component: consume the message via kafka
Here is binary value received in python component
b'10,8,111,98,106,101,99,116,73,100,26,21,10,2,83,54,18,7,115,97,109,115,117,110,103,26,6,8,128,10,16,192,7'
Then, I use below code to deserialize the message but it throws a message "Error parsing message"
from device_pb2 import DeviceConfiguration
device = DeviceConfiguration()
device.ParseFromString(message)
=> As I see that the ParseFromString doesn't work for above binary value and throws "Error parsing message". It only works if the bytes value is created by SerializeToString python code.
Note that: I'm able to deserialize the binary by using deserializeBinary (make it public) in Nodejs but there is no similar function in device_pb2.py
So, is there any way for me to deserialize the message in Python code?
Many Thanks.

How to replace/overwrite default header of EmailMultiAlternatives

Environment: Ubuntu 18.10, Python 2.7.15, Django 1.11.16
I'm trying to send an email containing an inline image. I have the following code:
msg = EmailMultiAlternatives(some_subject, some_body, 'from#some-domain.com', ['to#some#domain'])
img_data = open('path/to/image.png', 'rb').read()
img = MIMEImage(img_data)
msg.attach(img)
msg.send()
(I've only included the code that I think is relevant but I can add more on demand.)
The above properly works and the image is properly displayed on most of the email clients (about 7 of them, both mobile, desktop or webmail ones) that I tested on, with two exceptions: Mozilla Thunderbird 60 and some macOS native email client.
On Thunderbird the image is not displayed inline but at the very end of the message. On the macOS client, the image is displayed inline but additionally it is also displayed at the very end of the message.
I composed and sent a test message from another email client, containing an inline image which was properly displayed on both Thunderbird and macOS. I compared the headers of this message with the headers of the message generated by my code.
I noticed that the faulty message has the 'Content-Type' set to 'multipart/mixed' while the properly displayed message had the same header set to 'multipart/related'.
I saved the faulty message in an eml file and manually changed the value of that header and then loaded the message in Thunderbird. The message was properly displayed and the image was in the right place.
If I could set that header to the proper value, the problem would be solved.
So, my question is: is there any possibility to tell EmailMultiAlternatives to set 'Content-Type' : 'multipart/related' instead of the default value of 'multipart/mixed'?
I tried to add the header like this but it is not working:
msg = EmailMultiAlternatives(some_subject, some_body, 'from#some-domain.com', ['to#some#domain'], headers={'Content-Type' : 'multipart/related'})
I got the following error ( I use Amazon SES):
400 Bad Request
<ErrorResponse xmlns="http://ses.amazonaws.com/doc/2010-12-01/">
<Error>
<Type>Sender</Type>
<Code>InvalidParameterValue</Code>
<Message>Duplicate header 'Content-Type'.</Message>
</Error>
<RequestId>xxxxxxxxxx</RequestId>
</ErrorResponse>
If I can't modify that header, do you suggest any alternatives?
If you look at the source code, you'll see that EmailMultiAlternatives is a subclass of EmailMessage, which itself has a class attribute:
mixed_subtype = 'mixed'
So if you create your own subclass to override this, you should get what you need:
class EmailMultiAlternativesRelated(EmailMultiAlternatives):
mixed_subtype = 'related'
That's it, now you just use this new class, and it will use "multipart/related".
(the _create_attachments() method passes this subtype to python's SafeMIMEMultipart which creates the actual headers for each attachment.)

Request-streaming gRPC client request error

When I run my gRPC client and it attempts to stream a request to the server I get this error: "TypeError: has type list_iterator, but expected one of: bytes, unicode"
Do I need to encode the text I'm sending in some way? Error message makes some sense, as I am definitely passing in an iterator. I assumed from the gRPC documentation that this is what was needed. (https://grpc.io/docs/tutorials/basic/python.html#request-streaming-rpc)Anyway, sending a list or string yields a similar error.
At the moment I am sending a small test list of strings to the server in the request, but I plan to stream requests with very large amounts of text in the future.
Here's some of my client code.
def gen_tweet_space(text):
for tweet in text:
yield tweet
def run():
channel = grpc.insecure_channel('localhost:50050')
stub = ProseAndBabel_pb2_grpc.ProseAndBabelStub(channel)
while True:
iterator = iter(block_of_text)
response = stub.UserMarkov(ProseAndBabel_pb2.UserTweets(tweets=iterator))
Here's relevant server code:
def UserMarkov(self, request_iterator, context):
return ProseAndBabel_pb2.Babel(prose=markov.get_sentence(request_iterator.tweets))
Here's the proto where the rpc and messages are defined:
service ProseAndBabel {
rpc GetHaiku (BabelRequest) returns (Babel) {}
rpc GetBabel (BabelRequest) returns (Babel) {}
rpc UserMarkov (stream UserTweets) returns (UserBabel) {}
}
message BabelRequest{
string ask = 1;
}
message Babel{
string prose = 1;
}
message UserTweets{
string tweets = 1;
}
message UserBabel{
string prose = 1;
}
I've been successful getting the non-streaming rpc to work, but having trouble finding walkthroughs for request side streaming for python applications so I'm sure I'm missing something here. Any guidance/direction appreciated!
You need to pass the iterator of requests to the gRPC client stub, not to the protobuf constructor. The current code tries to instantiate a UserTweets protobuf with an iterator rather than an individual string, resulting in the type error.
response = stub.UserMarkov(ProseAndBabel_pb2.UserTweets(tweets=iterator))
You'll instead need to have your iterator to return instances of ProseAndBabel_pb2.UserTweets, each of which wraps one of the request strings you would like to send, and pass the iterator itself to the stub. Something like:
iterator = iter([ProseAndBabel_pb2.UserTweets(tweets=x) for x in block_of_text])
response = stub.UserMarkov(iterator)

Using Slack RTM API with Django 2.0

I am a beginner to the Django framework and I am building a Django app that uses the Slack RTM API.
I have a coded a program in python that performs the OAuth authentication process like so :
def initialize():
url="https://slack.com/api/rtm.connect"
payload={"token":"xxx"}
r=requests.post(url,payload)
res=json.loads(r.text)
url1=res['url']
ws = create_connection(url1)
return ws
My Requirement:
The stream of events I receive (from my slack channel that my slack app is added to) is processed to filter out events of the type - message ,then match the message with a regex pattern and then store the matched string in a database.
As a stand alone python program I am receiving the stream of events from my channel.
My questions:
How do I successfully integrate this code to Django so that I can
fulfill my requirement?
Do I put the code in templates/views? What is the
recommended method to process this stream of data?
def initialize():
url = "https://slack.com/api/rtm.connect"
r = requests.get(url, params={'token': '<YOUR TOKEN>'})
res = r.json()
url1=res['url']
ws = create_connection(url1) #Note: There is no function called create_connnection() so it will raise an error
return ws
if you read the API web methods, you see :
Preferred HTTP method: GET
See here: Slack rtm.connect method
look at the comment, and thats the right code, see the differences between this code and yours.
basically to get JSON from a request don't use json.loads because this search your local computer not the request
use r.json() so it call the json you got from r.
Note that r.text will return raw text output so when you want to get url it will not be identified, with r.json you can call the object url as stated about
Hope this help.
and please could you tell us more what you wanna do with this in view ? because template is a directory which contains all the HTML files which you don't need to work with.
but why views.py ?

Can't make GAE Channel API work on local computer

I am creating a small application to test how GAE Channel API works. I think I have done all as it's described in the documentation but when I launch it, it shows an error in FireFox error log about syntax in the beginning and then another repeating error that an element wasn't found that.
Here is the first error info:
Source: http://127.0.0.1:8080/_ah/channel/dev?command=connect&channel=channel-773698929-185804764220139124118
Line 1, symbol 1
Here is the url where my javascript code tries to connect repeatedly and it raises the second error:
http://127.0.0.1:8080/_ah/channel/dev?command=poll&channel=channel-2071442473-185804764220139124118&client=1
I get the token through a JSON request with jQuery $.get. Then I run this code to get the token and open the channel. The error begins to show just when I run socket = channel.open(handler):
var response = JSON.parse(data);
var token = response.token.toString();
channel = new goog.appengine.Channel(token);
var handler = {
'onopen': onOpened,
'onmessage': onMessage,
'onerror': function() {
},
'onclose': function() {
}
};
socket = channel.open(handler);
Here is the server side code in Python to open the channel:
class OpenChannel(webapp.RequestHandler):
def get(self):
user = users.get_current_user()
token = channel.create_channel(user.user_id())
serialized = json.dumps({'token': token})
self.response.headers['Content-Type'] = "application/json"
self.response.out.write(serialized)
What's my error and what can I do? Thanks!
It seems that Channel API works on localhost different way than on GAE hosting. I uploaded it to the cloud and it works well now. Though it looks like it working fine on the local computer, it shows permanent JS error repeating in the error log.
You could try removing the handler argument and adding the handlers as methods of the socket object i.e. socket.onopen = function() {}; etc. That worked for me. But you are right. According to this, you should be able to get this working by using the handler argument. Hmm.

Categories