edx-ace 1.11.1__py2.py3-none-any.whl → 1.11.3__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
edx_ace/__init__.py CHANGED
@@ -13,7 +13,7 @@ from .policy import Policy, PolicyResult
13
13
  from .recipient import Recipient
14
14
  from .recipient_resolver import RecipientResolver
15
15
 
16
- __version__ = '1.11.1'
16
+ __version__ = '1.11.3'
17
17
 
18
18
 
19
19
  __all__ = [
@@ -176,7 +176,9 @@ def get_channel_for_message(channel_type, message):
176
176
  channel_names = []
177
177
 
178
178
  if channel_type == ChannelType.EMAIL:
179
- if message.options.get('transactional'):
179
+ if message.options.get('override_default_channel'):
180
+ channel_names = [message.options.get('override_default_channel')]
181
+ elif message.options.get('transactional'):
180
182
  channel_names = [settings.ACE_CHANNEL_TRANSACTIONAL_EMAIL, settings.ACE_CHANNEL_DEFAULT_EMAIL]
181
183
  else:
182
184
  channel_names = [settings.ACE_CHANNEL_DEFAULT_EMAIL]
edx_ace/delivery.py CHANGED
@@ -10,8 +10,8 @@ import time
10
10
  from django.conf import settings
11
11
 
12
12
  from edx_ace.errors import RecoverableChannelDeliveryError
13
- from edx_ace.signals import ACE_MESSAGE_SENT
14
13
  from edx_ace.utils.date import get_current_time
14
+ from edx_ace.utils.signals import send_ace_message_sent_signal
15
15
 
16
16
  LOG = logging.getLogger(__name__)
17
17
 
@@ -61,7 +61,7 @@ def deliver(channel, rendered_message, message):
61
61
  message.report(f'{channel_type}_delivery_retried', num_seconds)
62
62
  else:
63
63
  message.report(f'{channel_type}_delivery_succeeded', True)
64
- ACE_MESSAGE_SENT.send(sender=channel, message=message)
64
+ send_ace_message_sent_signal(channel, message)
65
65
  return
66
66
 
67
67
  delivery_expired_report = f'{channel_type}_delivery_expired'
@@ -34,19 +34,19 @@ class TestDelivery(TestCase): # pylint: disable=missing-class-docstring
34
34
  )
35
35
  self.current_time = datetime.datetime.utcnow().replace(tzinfo=tzutc())
36
36
 
37
- @patch('edx_ace.delivery.ACE_MESSAGE_SENT.send')
37
+ @patch('edx_ace.delivery.send_ace_message_sent_signal')
38
38
  def test_happy_path(self, mock_ace_message_sent):
39
39
  deliver(self.mock_channel, sentinel.rendered_email, self.message)
40
40
  self.mock_channel.deliver.assert_called_once_with(self.message, sentinel.rendered_email)
41
41
  # check if ACE_MESSAGE_SENT is raised
42
- mock_ace_message_sent.assert_called_once_with(sender=self.mock_channel, message=self.message)
42
+ mock_ace_message_sent.assert_called_once_with(self.mock_channel, self.message)
43
43
 
44
44
  def test_fatal_error(self):
45
45
  self.mock_channel.deliver.side_effect = FatalChannelDeliveryError('testing')
46
46
  with self.assertRaises(FatalChannelDeliveryError):
47
47
  deliver(self.mock_channel, sentinel.rendered_email, self.message)
48
48
 
49
- @patch('edx_ace.delivery.ACE_MESSAGE_SENT.send')
49
+ @patch('edx_ace.delivery.send_ace_message_sent_signal')
50
50
  @patch('edx_ace.delivery.get_current_time')
51
51
  def test_custom_message_expiration(self, mock_get_current_time, mock_ace_message_sent):
52
52
  self.message.expiration_time = self.current_time - datetime.timedelta(seconds=10)
@@ -106,7 +106,7 @@ class TestDelivery(TestCase): # pylint: disable=missing-class-docstring
106
106
  assert mock_time.sleep.call_args_list == [call(1), call(1)]
107
107
  assert self.mock_channel.deliver.call_count == 3
108
108
 
109
- @patch('edx_ace.delivery.ACE_MESSAGE_SENT.send')
109
+ @patch('edx_ace.delivery.send_ace_message_sent_signal')
110
110
  def test_message_sent_signal_for_push_channel(self, mock_ace_message_sent):
111
111
  """
112
112
  Test that ACE_MESSAGE_SENT signal is sent when a message is delivered to a push channel.
@@ -117,4 +117,4 @@ class TestDelivery(TestCase): # pylint: disable=missing-class-docstring
117
117
  )
118
118
  deliver(mock_push_channel, sentinel.rendered_email, self.message)
119
119
  # check if ACE_MESSAGE_SENT is raised
120
- mock_ace_message_sent.assert_called_once_with(sender=mock_push_channel, message=self.message)
120
+ mock_ace_message_sent.assert_called_once_with(mock_push_channel, self.message)
@@ -0,0 +1,47 @@
1
+ """
2
+ Tests for the utils/signals module.
3
+ """
4
+ from django.test import TestCase
5
+
6
+ from edx_ace.utils.signals import make_serializable_object
7
+
8
+
9
+ class TestMakeSerializableObject(TestCase):
10
+ def test_primitive_types(self):
11
+ self.assertEqual(make_serializable_object(42), 42)
12
+ self.assertEqual(make_serializable_object(3.14), 3.14)
13
+ self.assertEqual(make_serializable_object("string"), "string")
14
+ self.assertEqual(make_serializable_object(True), True)
15
+ self.assertEqual(make_serializable_object(None), None)
16
+
17
+ def test_dict(self):
18
+ input_dict = {
19
+ "int": 1,
20
+ "float": 2.0,
21
+ "str": "test",
22
+ "bool": False,
23
+ "none": None,
24
+ "list": [1, 2, 3],
25
+ "nested_dict": {"key": "value"}
26
+ }
27
+ self.assertEqual(make_serializable_object(input_dict), input_dict)
28
+
29
+ def test_list(self):
30
+ input_list = [1, 2.0, "test", False, None, [1, 2, 3], {"key": "value"}]
31
+ self.assertEqual(make_serializable_object(input_list), input_list)
32
+
33
+ def test_non_serializable(self):
34
+ class NonSerializable:
35
+ pass
36
+
37
+ obj = NonSerializable()
38
+ self.assertEqual(make_serializable_object(obj), str(obj))
39
+
40
+ def test_non_serializable_list(self):
41
+ class NonSerializable:
42
+ pass
43
+
44
+ obj = NonSerializable()
45
+ obj2 = NonSerializable()
46
+ obj_list = [obj, obj2]
47
+ self.assertEqual(make_serializable_object(obj_list), [str(obj), str(obj2)])
@@ -0,0 +1,46 @@
1
+ """
2
+ Utils for signals.
3
+ """
4
+ from edx_ace.signals import ACE_MESSAGE_SENT
5
+
6
+
7
+ def make_serializable_object(obj):
8
+ """
9
+ Takes a dictionary/list and returns a dictionary/list with all the values converted
10
+ to JSON serializable objects.
11
+ """
12
+ try:
13
+ if isinstance(obj, (int, float, str, bool)) or obj is None:
14
+ return obj
15
+ elif isinstance(obj, dict):
16
+ return {key: make_serializable_object(value) for key, value in obj.items()}
17
+ elif isinstance(obj, list):
18
+ return [make_serializable_object(element) for element in obj]
19
+ except Exception: # pylint: disable=broad-except
20
+ pass
21
+ return str(obj)
22
+
23
+
24
+ def send_ace_message_sent_signal(channel, message):
25
+ """
26
+ Creates dictionary from message, makes it JSON serializable and
27
+ sends the ACE_MESSAGE_SENT signal.
28
+ """
29
+ try:
30
+ channel_name = channel.__class__.__name__
31
+ except AttributeError:
32
+ channel_name = 'Other'
33
+ data = {
34
+ 'name': message.name,
35
+ 'app_label': message.app_label,
36
+ 'recipient': {
37
+ 'email': getattr(message.recipient, 'email_address', ''),
38
+ 'user_id': getattr(message.recipient, 'lms_user_id', ''),
39
+ },
40
+ 'channel': channel_name,
41
+ 'context': message.context,
42
+ 'options': message.options,
43
+ 'uuid': str(message.uuid),
44
+ 'send_uuid': str(message.send_uuid),
45
+ }
46
+ ACE_MESSAGE_SENT.send(sender=channel, message=make_serializable_object(data))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: edx-ace
3
- Version: 1.11.1
3
+ Version: 1.11.3
4
4
  Summary: Framework for Messaging
5
5
  Home-page: https://github.com/openedx/edx-ace
6
6
  Author: edX
@@ -1,7 +1,7 @@
1
- edx_ace/__init__.py,sha256=NNRZBB6kXsBqSeXn-kM6K_JUeSKuKmsOrDq7zJFW1ec,636
1
+ edx_ace/__init__.py,sha256=Ro4txh3_BvOxSMMgQlibuMMDQCU7M943OCbj2MTUGb8,636
2
2
  edx_ace/ace.py,sha256=0nP8zvIWiME4qmpMT1PaV4nRDG6YR9Dxm7A6FGoBa8I,2501
3
3
  edx_ace/apps.py,sha256=xNedkdW6TNpm-W1uxnj3Vre2R1akkh2n_7DkSfKXmAk,216
4
- edx_ace/delivery.py,sha256=m_IOo4HTuuMZ61OOBZCA_TgLcfrME8BidWDutJmnaY0,2802
4
+ edx_ace/delivery.py,sha256=zo5lNHngycEn0tu-e3JM26njRVmaAttAH3D5ohz_468,2812
5
5
  edx_ace/errors.py,sha256=y0MqT55qXLkpn_r5LVhHcYuU2-zHs56CQTAbNCqb72k,1065
6
6
  edx_ace/message.py,sha256=lhmPor9vnaLvC4NPyRgB-obpGjGv9Lni0obcOUTgyCg,8340
7
7
  edx_ace/monitoring.py,sha256=6nEcAJMCr9keCTJw9JjGecTg_J1ubcGJfuGiFq2B8G4,257
@@ -12,7 +12,7 @@ edx_ace/recipient_resolver.py,sha256=ChY0cgLSt_HioKSHyuCh7iHSJOsBWuivsOvAc6QyedE
12
12
  edx_ace/renderers.py,sha256=eJcTWyRhny-3PLHDV4Rozk1TJ0fjsqgOcFOWO_TTngk,3143
13
13
  edx_ace/serialization.py,sha256=EptnQqbI9j5kVqdUDAlm2pcm3dUsFwsP9tAji3y5uqc,3775
14
14
  edx_ace/signals.py,sha256=7kwpw7SgpPP6TRTtTQeGEOZ2cD_AcD4sSrpVxd_a19w,160
15
- edx_ace/channel/__init__.py,sha256=l2qZdiQb2HFsMixWjqf50-si7aGr06M2MvEYc7XayjU,6890
15
+ edx_ace/channel/__init__.py,sha256=bQ8rpb_o0CvyWxZjOkmU9Au2S4kUCeKM8upvUb3yG7g,7030
16
16
  edx_ace/channel/braze.py,sha256=k-R9jZpiBQTV0FQ3Z2gOipVgxNpBMPSLBL71muh9go4,10240
17
17
  edx_ace/channel/django_email.py,sha256=9TNdiFJ2U3QjKEriUl3_9twAFkH-E2EmrWujStUOWN0,2174
18
18
  edx_ace/channel/file.py,sha256=_Jx8o5Cw8IpEdaF7g-ljF7CEqswBHmuwyupm_tkI2wk,3028
@@ -24,7 +24,7 @@ edx_ace/templatetags/acetags.py,sha256=CFVLb1j7oCN0mNNOpjaUHqQBEGlYZyRUgbYr9vS-S
24
24
  edx_ace/test_utils/__init__.py,sha256=HfJqvOqVNFS0dMpj4TnnXrTWHO8nutRFdA1Qja7ktfY,1087
25
25
  edx_ace/tests/test_ace.py,sha256=H5ss4ah-v5XDJ47udl6Ob6iSVdcX0qkjPI2h0kgWp1k,3278
26
26
  edx_ace/tests/test_date.py,sha256=RteoiCrc269BXnIerrtz8I0K1weldZ_Qg9Oc0Nd8ixs,639
27
- edx_ace/tests/test_delivery.py,sha256=0NYvFRWWcbEIdv5LE17EdYYcf9SE5g7mspC8poqPpNQ,5796
27
+ edx_ace/tests/test_delivery.py,sha256=6nTSm3y28U0J0ChfduVPxkRyMA-IVEZ9H8TkmSHktAI,5787
28
28
  edx_ace/tests/test_message.py,sha256=uAf3XltW605WieNGdi0u5p6bY_oSqLsmV5pHU3J_TiQ,4430
29
29
  edx_ace/tests/test_policy.py,sha256=T6Mm_q1Bi935WMBPS7sK5XbXM5izQ3y0KW0yiaQ5_GU,1597
30
30
  edx_ace/tests/test_presentation.py,sha256=elgVz_sR04h3KKs73G0qQBzt0CazOPWKrDF2rVC_R4U,541
@@ -36,13 +36,15 @@ edx_ace/tests/channel/test_push_notification.py,sha256=u6BBplfPwQLMRL02VFlWlNDEw
36
36
  edx_ace/tests/channel/test_sailthru.py,sha256=Hfs-v2y9N9H2u0LlA_cJkhcuU0iC02wzwTt4pHsRS7o,3197
37
37
  edx_ace/tests/test_templates/testapp/edx_ace/testmessage/email/body.html,sha256=gDeXQeQFnC2EFzdJ-OwWL7yDdkiR42sUYIxyeJJUD9s,646
38
38
  edx_ace/tests/test_templates/testapp/edx_ace/testmessage/email/head.html,sha256=XvxX2Go_eKUtG0Oo1qPPMOtdS2IoGi7PSY98Di_Ev3s,19
39
+ edx_ace/tests/utils/test_signals.py,sha256=k0F76oxcnECd95MeGw666YD3d2z-mIx4AS_MTYjwY5Q,1513
39
40
  edx_ace/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
40
41
  edx_ace/utils/date.py,sha256=Rmz3RAUCdd30hu1qcKH7FmAypaw1aSoZg-yfZig1c8A,1483
41
42
  edx_ace/utils/once.py,sha256=sY3szBh3gvvAjrKbKq4S2mCejompjh5YcYD7XOhzjGU,2024
42
43
  edx_ace/utils/plugins.py,sha256=U-l-eU2uWUiiwYV-H-2DfmwjoksqskAsYwS7QnThy2Q,2090
43
- edx_ace-1.11.1.dist-info/LICENSE.txt,sha256=VrSJ4gO4NCpskzfNHbaTB4VcN9Q213YdcHbpOZSwcOA,35138
44
- edx_ace-1.11.1.dist-info/METADATA,sha256=eTDhK8s6zluZDzmrBoanH8CN3hoVOqyVr8igrUydmi0,10106
45
- edx_ace-1.11.1.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
46
- edx_ace-1.11.1.dist-info/entry_points.txt,sha256=fiR8u0PqGyp2qIiJxcSrYhIZ3gEwl0vIMnTPWegXwRI,332
47
- edx_ace-1.11.1.dist-info/top_level.txt,sha256=5eg_80KI88VkeiCVqZUqcYcc_PfPOg8o1GA4HxsiRU8,8
48
- edx_ace-1.11.1.dist-info/RECORD,,
44
+ edx_ace/utils/signals.py,sha256=zvHE0qW-oQUKNhj2bwMu16-XEBmJyjraIgcr2w0oHRw,1494
45
+ edx_ace-1.11.3.dist-info/LICENSE.txt,sha256=VrSJ4gO4NCpskzfNHbaTB4VcN9Q213YdcHbpOZSwcOA,35138
46
+ edx_ace-1.11.3.dist-info/METADATA,sha256=e7DAzLVDD37_wilR5pbrElV3ovhbzLzFlq1AU_lGzRY,10106
47
+ edx_ace-1.11.3.dist-info/WHEEL,sha256=fS9sRbCBHs7VFcwJLnLXN1MZRR0_TVTxvXKzOnaSFs8,110
48
+ edx_ace-1.11.3.dist-info/entry_points.txt,sha256=fiR8u0PqGyp2qIiJxcSrYhIZ3gEwl0vIMnTPWegXwRI,332
49
+ edx_ace-1.11.3.dist-info/top_level.txt,sha256=5eg_80KI88VkeiCVqZUqcYcc_PfPOg8o1GA4HxsiRU8,8
50
+ edx_ace-1.11.3.dist-info/RECORD,,