API Documentation

Basic Interface

ACE (Automated Communications Engine) is a framework for automatically sending messages to users.

edx_ace exports the typical set of functions and classes needed to use ACE.

edx_ace.send(msg)

Send a message to a recipient.

Calling this method will result in an attempt being made to deliver the provided message to the recipient. Depending on the configured policies, it may be transmitted to them over one or more channels (email, sms, push etc).

The message must have valid values for all required fields in order for it to be sent. Different channels have different requirements, so care must be taken to ensure that all of the needed information is present in the message before calling ace.send().

Parameters:msg (Message) – The message to send.
class edx_ace.Message(app_label, name, recipient, expiration_time=None, context=NOTHING, send_uuid=None, language=None, log_level=None)

Bases: edx_ace.serialization.MessageAttributeSerializationMixin

A Message is the core piece of data that is passed into ACE. It captures the message, recipient, and all context needed to render the message for delivery.

Parameters:
  • app_label (str) – The name of the Django app that is sending this message. Used to look up the appropriate template during rendering. Required.
  • name (str) – The name of this type of message. Used to look up the appropriate template during rendering. Required.
  • recipient (Recipient) – The intended recipient of the message. Optional.
  • expiration_time (datetime) – The date and time at which this message expires. After this time, the message should not be delivered. Optional.
  • context (dict) – A dictionary to be supplied to the template at render time as the context.
  • send_uuid (uuid.UUID) – The uuid.UUID assigned to this bulk-send of many messages.
  • language (str) – The language the message should be rendered in. Optional.
app_label = Attribute(name='app_label', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
context = Attribute(name='context', default=Factory(factory=<function default_context_value>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
default_context_value()
expiration_time = Attribute(name='expiration_time', default=None, validator=<optional validator for <instance_of validator for type <type 'datetime.datetime'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
generate_uuid()
get_message_specific_logger(logger)
Parameters:logger (logging.Logger) – The logger to be adapted.

Returns: MessageLoggingAdapter that is specific to this message.

language = Attribute(name='language', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
log_id

The identity of this message for logging.

log_level = Attribute(name='log_level', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
name = Attribute(name='name', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
recipient = Attribute(name='recipient', default=NOTHING, validator=<optional validator for <instance_of validator for type <class 'edx_ace.recipient.Recipient'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
report(key, value)
report_basics()
send_uuid = Attribute(name='send_uuid', default=None, validator=<optional validator for <instance_of validator for type <class 'uuid.UUID'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
unique_name

A unique name for this message, used for logging and reporting.

Returns: str

uuid = Attribute(name='uuid', default=Factory(factory=<function generate_uuid>, takes_self=True), validator=<instance_of validator for type <class 'uuid.UUID'>>, repr=True, cmp=True, hash=None, init=False, convert=None, metadata=mappingproxy({}))
class edx_ace.MessageType(context=NOTHING, expiration_time=None, app_label=NOTHING, name=NOTHING, log_level=None)

Bases: edx_ace.serialization.MessageAttributeSerializationMixin

A class representing a type of Message. An instance of a MessageType is used for each batch send of messages.

Parameters:
  • context (dict) – Context to be supplied to all messages sent in this batch of messages.
  • expiration_time (datetime.datetime) – The time at which these messages expire.
  • app_label (str) – Override the Django app that is used to resolve the template for rendering. Defaults to APP_LABEL or to the app that the message type was defined in.
  • name (str) – Override the message name that is used to resolve the template for rendering. Defaults to NAME or to the name of the class.
APP_LABEL = None
NAME = None
app_label = Attribute(name='app_label', default=Factory(factory=<function default_app_label>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
context = Attribute(name='context', default=Factory(factory=<function default_context_value>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
default_app_label()
default_context_value()
default_name()
expiration_time = Attribute(name='expiration_time', default=None, validator=<optional validator for <instance_of validator for type <type 'datetime.datetime'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
generate_uuid()
log_level = Attribute(name='log_level', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
name = Attribute(name='name', default=Factory(factory=<function default_name>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
personalize(recipient, language, user_context)

Personalize this MessageType to a specific recipient, in order to send a specific message.

Parameters:
  • recipient (Recipient) – The intended recipient of the message. Optional.
  • language (str) – The language the message should be rendered in. Optional.
  • user_context (dict) – A dictionary containing recipient-specific context to be supplied to the template at render time.
Returns: A new Message that has been personalized to a
specific recipient.
uuid = Attribute(name='uuid', default=Factory(factory=<function generate_uuid>, takes_self=True), validator=<instance_of validator for type <class 'uuid.UUID'>>, repr=True, cmp=True, hash=None, init=False, convert=None, metadata=mappingproxy({}))
class edx_ace.Recipient(username, email_address=None)

Bases: edx_ace.serialization.MessageAttributeSerializationMixin

The target for a message.

Parameters:
  • username (str) – The username of the intended recipient.
  • email_address (str) – The email address of the intended recipient. Optional.
email_address = Attribute(name='email_address', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
username = Attribute(name='username', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
class edx_ace.RecipientResolver

Bases: object

This class represents a pattern for separating the content of a message (the MessageType) from the selection of recipients (the RecipientResolver).

send(msg_type, *args, **kwargs)

send() a Message personalized from msg_type to all recipients selected by this RecipientResolver.

Parameters:msg_type (MessageType) – An instantiated MessageType that describes the message batch to send.
class edx_ace.ChannelType

Bases: enum.Enum

All supported communication channels.

EMAIL = u'email'
PUSH = u'push'
class edx_ace.Channel

Bases: object

Channels deliver messages to users that have already passed through the presentation and policy steps.

Examples include email messages, push notifications, or in-browser messages. Implementations of this abstract class should not require any parameters be passed into their constructor since they are instantiated.

channel_type must be a ChannelType.

channel_type = None
deliver(message, rendered_message)

Transmit a rendered message to a recipient.

Parameters:
  • message (Message) – The message to transmit.
  • rendered_message (dict) – The rendered content of the message that has been personalized for this particular recipient.
classmethod enabled()

Validate settings to determine whether this channel can be enabled.

class edx_ace.Policy

Bases: object

A Policy allows an application to specify what Channel any specific Message shouldn’t be sent over. Policies are one of the primary extension mechanisms for ACE, and are registered using the entrypoint openedx.ace.policy.

check(message)

Validate the supplied Message against a specific delivery policy.

Parameters:message (Message) – The message to run the policy against.
Returns: PolicyResult
A PolicyResult that represents what channels the message should not be delivered over.
classmethod enabled()
class edx_ace.PolicyResult(deny=NOTHING)

Bases: object

Parameters:deny (set) – A set of ChannelType values that should be excluded when sending a message.
check_set_of_channel_types(attribute, set_value)
deny = Attribute(name='deny', default=Factory(factory=<type 'set'>, takes_self=False), validator=<function check_set_of_channel_types>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))

Sending Messages

The main entry point for sending messages with ACE.

Usage:

from edx_ace import ace
from edx_ace.messages import Message

msg = Message(
    name="test_message",
    app_label="my_app",
    recipient=Recipient(username='a_user', email='a_user@example.com'),
    language='en',
    context={
        'stuff': 'to personalize the message',
    }
)
ace.send(msg)
edx_ace.ace.send(msg)

Send a message to a recipient.

Calling this method will result in an attempt being made to deliver the provided message to the recipient. Depending on the configured policies, it may be transmitted to them over one or more channels (email, sms, push etc).

The message must have valid values for all required fields in order for it to be sent. Different channels have different requirements, so care must be taken to ensure that all of the needed information is present in the message before calling ace.send().

Parameters:msg (Message) – The message to send.

Delivery

edx_ace.channel exposes the ACE extension point needed to add new delivery Channel instances to an ACE application.

Developers wanting to add a new deliver channel should subclass Channel, and then add an entry to the openedx.ace.channel entrypoint in their setup.py.

class edx_ace.channel.Channel

Bases: object

Channels deliver messages to users that have already passed through the presentation and policy steps.

Examples include email messages, push notifications, or in-browser messages. Implementations of this abstract class should not require any parameters be passed into their constructor since they are instantiated.

channel_type must be a ChannelType.

channel_type = None
deliver(message, rendered_message)

Transmit a rendered message to a recipient.

Parameters:
  • message (Message) – The message to transmit.
  • rendered_message (dict) – The rendered content of the message that has been personalized for this particular recipient.
classmethod enabled()

Validate settings to determine whether this channel can be enabled.

class edx_ace.channel.ChannelType

Bases: enum.Enum

All supported communication channels.

EMAIL = u'email'
PUSH = u'push'
edx_ace.channel.channels()

Gathers all available channels.

Note that this function loads all available channels from entry points. It expects the Django setting ACE_ENABLED_CHANNELS to be a list of plugin names that should be enabled. Only one plugin per channel type should appear in that list.

Raises:ValueError – If multiple plugins are enabled for the same channel type.
Returns:A mapping of channel types to instances of channel objects that can be used to deliver messages.
Return type:dict

edx_ace.channel.sailthru

edx_ace.channel.sailthru implements a SailThru-based email delivery channel for ACE.

class edx_ace.channel.sailthru.RecoverableErrorCodes

Bases: enum.Enum

These error codes are present in responses to requests that can (and should) be retried after waiting for a bit.

INTERNAL_ERROR = 9

Something’s gone wrong on Sailthru’s end. Your request was probably not saved - try waiting a moment and trying again.

RATE_LIMIT = 43

Too many [type] requests this minute to /[endpoint] API – You have exceeded the limit of requests per minute for the given type (GET or POST) and endpoint. For limit details, see the Rate Limiting section on the API Technical Details page.

class edx_ace.channel.sailthru.ResponseHeaders

Bases: enum.Enum

These are special headers returned in responses from the Sailthru REST API.

RATE_LIMIT_REMAINING = u'X-Rate-Limit-Remaining'
RATE_LIMIT_RESET = u'X-Rate-Limit-Reset'
class edx_ace.channel.sailthru.SailthruEmailChannel

Bases: edx_ace.channel.Channel

An email channel for delivering messages to users using Sailthru.

This channel makes use of the Sailthru REST API to send messages. It is designed for “at most once” delivery of messages. It will make a reasonable attempt to deliver the message and give up if it can’t. It also only confirms that Sailthru has received the request to send the email, it doesn’t actually confirm that it made it to the recipient.

The integration with Sailthru requires several Django settings to be defined.

Example

Sample settings:

.. settings_start
ACE_CHANNEL_SAILTHRU_DEBUG = False
ACE_CHANNEL_SAILTHRU_TEMPLATE_NAME = "Some template name"
ACE_CHANNEL_SAILTHRU_API_KEY = "1234567890"
ACE_CHANNEL_SAILTHRU_API_SECRET = "this is secret"
.. settings_end

The named template in Sailthru should be minimal, most of the rendering happens within ACE. The “From Name” field should be set to {{ace_template_from_name}}. The “Subject” field should be set to {{ace_template_subject}}. The “Code” for the template should be:

<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
    <head>
        {{ace_template_head_html}}
    </head>
    <body>
        {body_html = replace(ace_template_body_html, '{view_url}', view_url)}
        {body_html = replace(body_html, '{optout_confirm_url}', optout_confirm_url)}
        {body_html = replace(body_html, '{forward_url}', forward_url)}
        {body_html = replace(body_html, '{beacon_src}', beacon_src)}
        {body_html}
        <span id="sailthru-message-id" style="display: none;">{message_id()}</span>
        <a href="{optout_confirm_url}" style="display: none;"></a>
    </body>
</html>
channel_type = u'email'
deliver(message, rendered_message)
classmethod enabled()

Returns: True iff all required settings are not empty and the Sailthru client library is installed.

Exceptions

edx_ace.errors exposes all exceptions that are specific to ACE.

exception edx_ace.errors.ChannelError

Bases: exceptions.Exception

Indicates something went wrong in a delivery channel.

exception edx_ace.errors.FatalChannelDeliveryError

Bases: edx_ace.errors.ChannelError

A fatal error occurred during channel delivery. Do not retry.

exception edx_ace.errors.InvalidMessageError

Bases: exceptions.Exception

Encountered a message that cannot be sent due to missing or inconsistent information.

exception edx_ace.errors.RecoverableChannelDeliveryError(message, next_attempt_time)

Bases: edx_ace.errors.ChannelError

An error occurred during channel delivery that is non-fatal. The caller should re-attempt at a later time.

exception edx_ace.errors.UnsupportedChannelError

Bases: edx_ace.errors.ChannelError

Raised when an attempt is made to process a message for an unsupported channel.

Messages

edx_ace.message contains the core Message and MessageType classes, which allow specification of the content to be delivered by ACE.

class edx_ace.message.Message(app_label, name, recipient, expiration_time=None, context=NOTHING, send_uuid=None, language=None, log_level=None)

Bases: edx_ace.serialization.MessageAttributeSerializationMixin

A Message is the core piece of data that is passed into ACE. It captures the message, recipient, and all context needed to render the message for delivery.

Parameters:
  • app_label (str) – The name of the Django app that is sending this message. Used to look up the appropriate template during rendering. Required.
  • name (str) – The name of this type of message. Used to look up the appropriate template during rendering. Required.
  • recipient (Recipient) – The intended recipient of the message. Optional.
  • expiration_time (datetime) – The date and time at which this message expires. After this time, the message should not be delivered. Optional.
  • context (dict) – A dictionary to be supplied to the template at render time as the context.
  • send_uuid (uuid.UUID) – The uuid.UUID assigned to this bulk-send of many messages.
  • language (str) – The language the message should be rendered in. Optional.
app_label = Attribute(name='app_label', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
context = Attribute(name='context', default=Factory(factory=<function default_context_value>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
default_context_value()
expiration_time = Attribute(name='expiration_time', default=None, validator=<optional validator for <instance_of validator for type <type 'datetime.datetime'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
generate_uuid()
get_message_specific_logger(logger)
Parameters:logger (logging.Logger) – The logger to be adapted.

Returns: MessageLoggingAdapter that is specific to this message.

language = Attribute(name='language', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
log_id

The identity of this message for logging.

log_level = Attribute(name='log_level', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
name = Attribute(name='name', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
recipient = Attribute(name='recipient', default=NOTHING, validator=<optional validator for <instance_of validator for type <class 'edx_ace.recipient.Recipient'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
report(key, value)
report_basics()
send_uuid = Attribute(name='send_uuid', default=None, validator=<optional validator for <instance_of validator for type <class 'uuid.UUID'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
unique_name

A unique name for this message, used for logging and reporting.

Returns: str

uuid = Attribute(name='uuid', default=Factory(factory=<function generate_uuid>, takes_self=True), validator=<instance_of validator for type <class 'uuid.UUID'>>, repr=True, cmp=True, hash=None, init=False, convert=None, metadata=mappingproxy({}))
class edx_ace.message.MessageLoggingAdapter(logger, extra)

Bases: logging.LoggerAdapter

A logging.LoggingAdapter that prefixes log items with a message log_id.ABCMeta

Expects a message key in its extra argument which should contain the Message being logged for.

debug(msg, *args, **kwargs)
process(msg, kwargs)
class edx_ace.message.MessageType(context=NOTHING, expiration_time=None, app_label=NOTHING, name=NOTHING, log_level=None)

Bases: edx_ace.serialization.MessageAttributeSerializationMixin

A class representing a type of Message. An instance of a MessageType is used for each batch send of messages.

Parameters:
  • context (dict) – Context to be supplied to all messages sent in this batch of messages.
  • expiration_time (datetime.datetime) – The time at which these messages expire.
  • app_label (str) – Override the Django app that is used to resolve the template for rendering. Defaults to APP_LABEL or to the app that the message type was defined in.
  • name (str) – Override the message name that is used to resolve the template for rendering. Defaults to NAME or to the name of the class.
APP_LABEL = None
NAME = None
app_label = Attribute(name='app_label', default=Factory(factory=<function default_app_label>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
context = Attribute(name='context', default=Factory(factory=<function default_context_value>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
default_app_label()
default_context_value()
default_name()
expiration_time = Attribute(name='expiration_time', default=None, validator=<optional validator for <instance_of validator for type <type 'datetime.datetime'>> or None>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
generate_uuid()
log_level = Attribute(name='log_level', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
name = Attribute(name='name', default=Factory(factory=<function default_name>, takes_self=True), validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
personalize(recipient, language, user_context)

Personalize this MessageType to a specific recipient, in order to send a specific message.

Parameters:
  • recipient (Recipient) – The intended recipient of the message. Optional.
  • language (str) – The language the message should be rendered in. Optional.
  • user_context (dict) – A dictionary containing recipient-specific context to be supplied to the template at render time.
Returns: A new Message that has been personalized to a
specific recipient.
uuid = Attribute(name='uuid', default=Factory(factory=<function generate_uuid>, takes_self=True), validator=<instance_of validator for type <class 'uuid.UUID'>>, repr=True, cmp=True, hash=None, init=False, convert=None, metadata=mappingproxy({}))

Monitoring

edx_ace.monitoring exposes functions that are useful for reporting ACE message delivery stats to monitoring services.

edx_ace.monitoring.report(key, value)
edx_ace.monitoring.report_to_newrelic(key, value)

Delivery Policy

edx_ace.policy contains all classes relating to message policies.

These policies manage which messages should be sent over which channels, and are a point of pluggability in ACE.

class edx_ace.policy.Policy

Bases: object

A Policy allows an application to specify what Channel any specific Message shouldn’t be sent over. Policies are one of the primary extension mechanisms for ACE, and are registered using the entrypoint openedx.ace.policy.

check(message)

Validate the supplied Message against a specific delivery policy.

Parameters:message (Message) – The message to run the policy against.
Returns: PolicyResult
A PolicyResult that represents what channels the message should not be delivered over.
classmethod enabled()
class edx_ace.policy.PolicyResult(deny=NOTHING)

Bases: object

Parameters:deny (set) – A set of ChannelType values that should be excluded when sending a message.
check_set_of_channel_types(attribute, set_value)
deny = Attribute(name='deny', default=Factory(factory=<type 'set'>, takes_self=False), validator=<function check_set_of_channel_types>, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
edx_ace.policy.channels_for(message)
Parameters:message (Message) – The message apply policies to.
Returns: set
A set of ChannelType values that are allowed by all policies applied to the message.
edx_ace.policy.policies()

Message Presentation

edx_ace.renderers contains the classes used by ACE to render messages for particular types of delivery channels. Each ChannelType has a distinct subclass of AbstractRenderer associated with it, which is used to render messages for all Channel subclasses of that type.

class edx_ace.renderers.AbstractRenderer

Bases: object

Base class for message renderers.

A message renderer is responsible for taking one, or more, templates, and context, and outputting a rendered message for a specific message channel (e.g. email, SMS, push notification).

channel = None
get_template_for_message(message, filename)
Parameters:
  • message (Message) – The message being rendered.
  • filename (str) – The basename of the template file to look up.
Returns:

The full template path to the template to render.

render(message)

Renders the given message.

Parameters:message
rendered_message_cls = None
class edx_ace.renderers.EmailRenderer

Bases: edx_ace.renderers.AbstractRenderer

A renderer for ChannelType.EMAIL channels.

channel = u'email'
rendered_message_cls

alias of RenderedEmail

class edx_ace.renderers.RenderedEmail(from_name, subject, body_html, head_html, body)

Bases: object

Encapsulates all values needed to send a Message over an ChannelType.EMAIL.

body = Attribute(name='body', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
body_html = Attribute(name='body_html', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
from_name = Attribute(name='from_name', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
head_html = Attribute(name='head_html', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
subject = Attribute(name='subject', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))

An internal module that manages the presentation/rendering step of the ACE pipeline.

edx_ace.presentation.render(channel, message)

Returns the rendered content for the given channel and message.

Message Recipients

edx_ace.recipient contains Recipient, which captures all targeting information needed to deliver a message to some user.

class edx_ace.recipient.Recipient(username, email_address=None)

Bases: edx_ace.serialization.MessageAttributeSerializationMixin

The target for a message.

Parameters:
  • username (str) – The username of the intended recipient.
  • email_address (str) – The email address of the intended recipient. Optional.
email_address = Attribute(name='email_address', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))
username = Attribute(name='username', default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))

edx_ace.recipient_resolver contains the RecipientResolver, which facilitates a design pattern that separates message content from recipient lists.

class edx_ace.recipient_resolver.RecipientResolver

Bases: object

This class represents a pattern for separating the content of a message (the MessageType) from the selection of recipients (the RecipientResolver).

send(msg_type, *args, **kwargs)

send() a Message personalized from msg_type to all recipients selected by this RecipientResolver.

Parameters:msg_type (MessageType) – An instantiated MessageType that describes the message batch to send.

Serialization

edx_ace.serialization contains MessageAttributeSerializationMixin, which allows messages to be round-tripped through JSON, and MessageEncoder, which actually performs the JSON encoding.

class edx_ace.serialization.MessageAttributeSerializationMixin

Bases: object

This mixin allows an object to be serialized to (and deserialized from) a JSON string.

__str__() and from_string() function as inverses, and are the primary point of interaction with this mixin by outside clients.

to_json() is used to recursively convert the object to a python dictionary that can then be encoded to a JSON string.

classmethod from_string(string_value)

Decode a JSON-encoded string representation of this type.

Parameters:string_value (str) – The JSON string to decode.
Returns:An instance of this class.
to_json()
Returns: dict
a python dictionary containing all serializable fields of this object, suitable for JSON-encoding.
class edx_ace.serialization.MessageEncoder(skipkeys=False, ensure_ascii=True, check_circular=True, allow_nan=True, sort_keys=False, indent=None, separators=None, encoding='utf-8', default=None)

Bases: json.encoder.JSONEncoder

default(o)

Utils

edx_ace.utils.date

edx_ace.utils.date contains utility functions used for serializing and deserializing dates. It is intended for internal ACE use.

edx_ace.utils.date.deserialize(timestamp_iso8601_str)

Deserialize a datetime object from an ISO8601 formatted string.

Parameters:timestamp_iso8601_str (basestring) – A timestamp as an ISO8601 formatted string.
Returns:A timezone-aware python datetime object.
Return type:datetime
edx_ace.utils.date.get_current_time()

The current time in the UTC timezone as a timezone-aware datetime object.

edx_ace.utils.date.serialize(timestamp_obj)

Serialize a datetime object to an ISO8601 formatted string.

Parameters:timestamp_obj (datetime) – The timestamp to serialize.
Returns:A string representation of the timestamp in ISO8601 format.
Return type:basestring

edx_ace.utils.once

edx_ace.utils.once provides the ability to create a module-level function that caches it’s result after the first call (this can be used for lazy-loading expensive computations).

edx_ace.utils.once.once(func)

Decorates a function that will be called exactly once.

After the function is called once, its result is stored in memory and immediately returned to subsequent callers instead of calling the decorated function again.

Examples

An incrementing value:

_counter = 0

@once
def get_counter():
    global _counter
    _counter += 1
    return _counter

def get_counter_updating():
    global _counter
    _counter += 1
    return _counter

print(get_counter())  # This will print "0"
print(get_counter_updating()) # This will print "1"
print(get_counter())  # This will also print "0"
print(get_counter_updating()) # This will print "2"

Lazy loading:

@once
def load_config():
    with open('config.json', 'r') as cfg_file:
        return json.load(cfg_file)

cfg = load_config()  # This will do the relatively expensive operation to
                     # read the file from disk.
cfg2 = load_config() # This call will not reload the file from disk, it
                     # will use the value returned by the first invocation
                     # of this function.
Parameters:func (callable) – The function that should be called exactly once.
Returns:The wrapped function.
Return type:callable

edx_ace.utils.plugins

edx_ace.utils.plugins contains utility functions used to make working with the ACE plugin system easier. These are intended for internal use by ACE.

edx_ace.utils.plugins.check_plugin(extension, namespace, names=None)

Check the extension to see if it’s enabled.

Parameters:
  • extension (stevedore.extension.Extension) – The extension to check.
  • namespace (basestring) – The namespace that the extension was loaded from.
  • names (list) – A whitelist of extensions that should be checked.
Returns:

Whether or not this extension is enabled and should be used.

Return type:

bool

edx_ace.utils.plugins.get_manager(namespace, names=None)

Get the stevedore extension manager for this namespace.

Parameters:
  • namespace (basestring) – The entry point namespace to load plugins for.
  • names (list) – A list of names to load. If this is None then all extension will be loaded from this namespace.
Returns:

Extension manager with all extensions instantiated.

Return type:

stevedore.enabled.EnabledExtensionManager

edx_ace.utils.plugins.get_plugins(namespace, names=None)

Get all extensions for this namespace and list of names.

Parameters:
  • namespace (basestring) – The entry point namespace to load plugins for.
  • names (list) – A list of names to load. If this is None then all extension will be loaded from this namespace.
Returns:

A list of extensions.

Return type:

list

Testing

edx_ace.test_utils

Test utilities.

Since py.test discourages putting __init__.py into test directory (i.e. making tests a package) one cannot import from anywhere under tests folder. However, some utility classes/methods might be useful in multiple test modules (i.e. factoryboy factories, base test classes). So this package is the place to put them.

class edx_ace.test_utils.StubPolicy(deny_value)

Bases: edx_ace.policy.Policy

check(message)
edx_ace.test_utils.patch_channels(test_case, channels)

Set active channels for the duration of a test.

Parameters:
  • test_case (unittest.TestCase) – The test case that is running
  • channels – The set of active channels to return from edx_ace.delivery.channels()
edx_ace.test_utils.patch_policies(test_case, policies)

Set active policies for the duration of a test.

Parameters:

Internal

Delivery

Functions for delivering ACE messages.

This is an internal interface used by ace.send().

edx_ace.delivery.deliver(channel_type, rendered_message, message)

Deliver a message via a particular channel.

Parameters:
  • channel_type (ChannelType) – The channel type to deliver the channel over.
  • rendered_message (object) – Each attribute of this object contains rendered content.
  • message (Message) – The message that is being sent.
Raises:

UnsupportedChannelError – If no channel of the requested channel type is available.