Contents
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. |
---|
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: |
---|
enabled
()¶Validate settings to determine whether this channel can be enabled.
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.
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.
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'¶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)¶enabled
()¶Returns: True iff all required settings are not empty and the Sailthru client library is installed.
edx_ace.errors.
ChannelError
¶Bases: exceptions.Exception
Indicates something went wrong in a delivery channel.
edx_ace.errors.
FatalChannelDeliveryError
¶Bases: edx_ace.errors.ChannelError
A fatal error occurred during channel delivery. Do not retry.
edx_ace.errors.
InvalidMessageError
¶Bases: exceptions.Exception
Encountered a message that cannot be sent due to missing or inconsistent information.
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.
edx_ace.errors.
UnsupportedChannelError
¶Bases: edx_ace.errors.ChannelError
Raised when an attempt is made to process a message for an unsupported channel.
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
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)¶language
= Attribute(name='language', default=None, validator=None, repr=True, cmp=True, hash=None, init=True, convert=None, metadata=mappingproxy({}))¶log_id
¶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
¶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({}))¶edx_ace.message.
MessageLoggingAdapter
(logger, extra)¶Bases: logging.LoggerAdapter
debug
(msg, *args, **kwargs)¶process
(msg, kwargs)¶edx_ace.message.
MessageType
(context=NOTHING, expiration_time=None, app_label=NOTHING, name=NOTHING, log_level=None)¶Bases: edx_ace.serialization.MessageAttributeSerializationMixin
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)¶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({}))¶edx_ace.monitoring.
report
(key, value)¶edx_ace.monitoring.
report_to_newrelic
(key, value)¶edx_ace.policy.
Policy
¶Bases: object
check
(message)¶Returns PolicyResult.
enabled
()¶edx_ace.policy.
PolicyResult
(deny=NOTHING)¶Bases: object
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)¶edx_ace.policy.
policies
()¶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)¶render
(message)¶Renders the given message.
Parameters: | message – |
---|
rendered_message_cls
= None¶edx_ace.renderers.
EmailRenderer
¶Bases: edx_ace.renderers.AbstractRenderer
channel
= u'email'¶rendered_message_cls
¶alias of RenderedEmail
edx_ace.renderers.
RenderedEmail
(from_name, subject, body_html, head_html, body)¶Bases: object
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({}))¶edx_ace.presentation.
render
(channel, message)¶Returns the rendered content for the given channel and message.
edx_ace.recipient.
Recipient
(username, email_address=None)¶Bases: edx_ace.serialization.MessageAttributeSerializationMixin
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.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.once.
once
(fn)¶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: | fn (callable) – The function that should be called exactly once. |
---|---|
Returns: | The wrapped function. |
Return type: | callable |
edx_ace.utils.plugins.
check_plugin
(extension, namespace, names=None)¶Check the extension to see if it’s enabled.
Parameters: |
|
---|---|
Returns: | Whether or not this extension is enabled and should be used. |
Return type: |
edx_ace.utils.plugins.
get_manager
(namespace, names=None)¶Get the stevedore extension manager for this namespace.
Parameters: |
|
---|---|
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: |
|
---|---|
Returns: | A list of extensions. |
Return type: |
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.
edx_ace.test_utils.
StubPolicy
(deny_value)¶Bases: edx_ace.policy.Policy
check
(message)¶edx_ace.test_utils.
patch_channels
(test_case, channels)¶edx_ace.test_utils.
patch_policies
(test_case, policies)¶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: |
|
---|---|
Raises: |
|