'Sends a message to all of a topic\'s subscribed endpoints
:type topic: string
:param topic: The topic you want to publish to.
:type message: string
:param message: The message you want to send to the topic.
Messages must be UTF-8 encoded strings and
be at most 4KB in size.
:type message_structure: string
:param message_structure: Optional parameter. If left as ``None``,
plain text will be sent. If set to ``json``,
your message should be a JSON string that
matches the structure described at
http://docs.aws.amazon.com/sns/latest/dg/PublishTopic.html#sns-message-formatting-by-protocol
:type message_attributes: dict
:param message_attributes: Message attributes to set. Should be
of the form:
.. code-block:: python
"name1": {
"data_type": "Number",
"string_value": "42"
"name2": {
"data_type": "String",
"string_value": "Bob"
:type subject: string
:param subject: Optional parameter to be used as the "Subject"
line of the email notifications.
:type target_arn: string
:param target_arn: Optional parameter for either TopicArn or
EndpointArn, but not both.'

def publish(self, topic=None, message=None, subject=None, target_arn=None, message_structure=None, message_attributes=None):

    if (message is None):
        raise TypeError("'message'    is    a    required    parameter")
    params = {'Message': message}
    if (subject is not None):
        params['Subject'] = subject
    if (topic is not None):
        params['TopicArn'] = topic
    if (target_arn is not None):
        params['TargetArn'] = target_arn
    if (message_structure is not None):
        params['MessageStructure'] = message_structure
    if (message_attributes is not None):
        keys = sorted(message_attributes.keys())
        for (i, name) in enumerate(keys, start=1):
            attribute = message_attributes[name]
            params['MessageAttributes.entry.{0}.Name'.format(i)] = name
            if ('data_type' in attribute):
                params['MessageAttributes.entry.{0}.Value.DataType'.format(i)] = attribute['data_type']
            if ('string_value' in attribute):
                params['MessageAttributes.entry.{0}.Value.StringValue'.format(i)] = attribute['string_value']
            if ('binary_value' in attribute):
                params['MessageAttributes.entry.{0}.Value.BinaryValue'.format(i)] = attribute['binary_value']
    return self._make_request('Publish', params, '/', 'POST')
