customerio 2.1__tar.gz → 2.2__tar.gz

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.
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: customerio
3
- Version: 2.1
3
+ Version: 2.2
4
4
  Summary: Customer.io Python bindings.
5
5
  Home-page: https://github.com/customerio/customerio-python
6
6
  Author: Peaberry Software Inc.
7
7
  Author-email: support@customerio.com
8
8
  License: BSD
9
- Platform: UNKNOWN
10
9
  Classifier: Environment :: Web Environment
11
10
  Classifier: Intended Audience :: Developers
12
11
  Classifier: License :: OSI Approved :: BSD License
@@ -18,6 +17,3 @@ Classifier: Programming Language :: Python :: 3.8
18
17
  Classifier: Programming Language :: Python :: 3.9
19
18
  License-File: LICENSE
20
19
  License-File: AUTHORS
21
-
22
- UNKNOWN
23
-
@@ -1,8 +1,7 @@
1
- <p align="center">
1
+ <p align=center>
2
2
  <a href="https://customer.io">
3
- <img src="https://user-images.githubusercontent.com/6409227/144680509-907ee093-d7ad-4a9c-b0a5-f640eeb060cd.png" height="60">
3
+ <img src="https://avatars.githubusercontent.com/u/1152079?s=200&v=4" height="60">
4
4
  </a>
5
- <p align="center">Power automated communication that people like to receive.</p>
6
5
  </p>
7
6
 
8
7
  [![Gitpod Ready-to-Code](https://img.shields.io/badge/Gitpod-Ready--to--Code-blueviolet?logo=gitpod)](https://gitpod.io/#https://github.com/customerio/customerio-python/)
@@ -14,7 +13,7 @@
14
13
 
15
14
  # Customer.io Python
16
15
 
17
- This module has been tested with Python 3.6, 3.7, 3.8 and 3.9.
16
+ This module has been tested with Python 3.6, 3.7, 3.8 and 3.9. If you're new to Customer.io, we recommend that you integrate with our [Data Pipelines Python library](https://github.com/customerio/cdp-analytics-python) instead.
18
17
 
19
18
  ## Installing
20
19
 
@@ -54,7 +53,7 @@ values for that field.
54
53
 
55
54
  You can pass any keyword arguments to the `identify` and `track` methods. These kwargs will be converted to custom attributes.
56
55
 
57
- See original REST documentation [here](http://customer.io/docs/api/rest.html#section-Creating_or_updating_customers)
56
+ See original REST documentation [here](http://customer.io/docs/api/track/#operation/identify)
58
57
 
59
58
  ### Track a custom event
60
59
 
@@ -70,7 +69,7 @@ cio.track(customer_id="5", name='purchased', price=23.45, product="widget")
70
69
 
71
70
  You can pass any keyword arguments to the `identify` and `track` methods. These kwargs will be converted to custom attributes.
72
71
 
73
- See original REST documentation [here](http://customer.io/docs/api/rest.html#section-Track_a_custom_event)
72
+ See original REST documentation [here](http://customer.io/docs/api/track/#operation/track)
74
73
 
75
74
  ### Backfill a custom event
76
75
 
@@ -95,7 +94,7 @@ Event timestamp may be passed as a ```datetime.datetime``` object, an integer or
95
94
 
96
95
  Keyword arguments to backfill work the same as a call to ```cio.track```.
97
96
 
98
- See original REST documentation [here](http://customer.io/docs/api/rest.html#section-Track_a_custom_event)
97
+ See original REST documentation [here](http://customer.io/docs/api/track/#operation/track)
99
98
 
100
99
  ### Track an anonymous event
101
100
 
@@ -107,7 +106,7 @@ An anonymous event is an event associated with a person you haven't identified.
107
106
 
108
107
  #### Anonymous invite events
109
108
 
110
- If you previously sent [invite events](https://customer.io/docs/anonymous-invite-emails/), you can achieve the same functionality by sending an anonymous event with the anonymous identifier set to `None`. To send anonymous invites, your event *must* include a `recipient` attribute.
109
+ If you previously sent [invite events](https://customer.io/docs/journeys/anonymous-invite-emails/), you can achieve the same functionality by sending an anonymous event with the anonymous identifier set to `None`. To send anonymous invites, your event *must* include a `recipient` attribute.
111
110
 
112
111
  ```python
113
112
  cio.track_anonymous(anonymous_id=None, name="invite", first_name="alex", recipient="alex.person@example.com")
@@ -122,7 +121,7 @@ Deletes the customer profile for a specified customer.
122
121
 
123
122
  This method returns nothing. Attempts to delete non-existent customers will not raise any errors.
124
123
 
125
- See original REST documentation [here](http://customer.io/docs/api/rest.html#section-Deleting_customers)
124
+ See original REST documentation [here](https://customer.io/docs/api/track/#operation/delete)
126
125
 
127
126
 
128
127
  You can pass any keyword arguments to the `identify` and `track` methods. These kwargs will be converted to custom attributes.
@@ -175,7 +174,7 @@ cio.suppress(customer_id="1")
175
174
 
176
175
  Suppresses the specified customer. They will be deleted from Customer.io, and we will ignore all further attempts to identify or track activity for the suppressed customer ID
177
176
 
178
- See REST documentation [here](https://learn.customer.io/api/#apisuppress_add)
177
+ See REST documentation [here](https://customer.io/docs/api/track/#operation/suppress)
179
178
 
180
179
  ### Unsuppress a customer
181
180
  ```python
@@ -184,22 +183,22 @@ cio.unsuppress(customer_id="1")
184
183
 
185
184
  Unsuppresses the specified customer. We will remove the supplied id from our suppression list and start accepting new identify and track calls for the customer as normal
186
185
 
187
- See REST documentation [here](https://learn.customer.io/api/#apisuppress_delete)
186
+ See REST documentation [here](https://customer.io/docs/api/track/#operation/unsuppress)
188
187
 
189
188
  ### Send Transactional Messages
190
189
 
191
- To use the [Transactional API](https://customer.io/docs/transactional-api), instantiate the Customer.io object using an [app key](https://customer.io/docs/managing-credentials#app-api-keys) and create a request object for your message type.
190
+ To use the [Transactional API](https://customer.io/docs/journeys/transactional-api), instantiate the Customer.io object using an [app key](https://customer.io/docs/managing-credentials#app-api-keys) and create a request object for your message type.
192
191
 
193
192
  ## Email
194
193
 
195
194
  SendEmailRequest requires:
196
- * `transactional_message_id`: the ID of the transactional message you want to send, or the `body`, `from`, and `subject` of a new message.
195
+ * `transactional_message_id`: the ID of the transactional message you want to send, or the `body`, `_from`, and `subject` of a new message.
197
196
  * `to`: the email address of your recipients
198
197
  * an `identifiers` object containing the `id` of your recipient. If the `id` does not exist, Customer.io will create it.
199
198
  * a `message_data` object containing properties that you want reference in your message using Liquid.
200
199
  * You can also send attachments with your message. Use `attach` to encode attachments.
201
200
 
202
- Use `send_email` referencing your request to send a transactional message. [Learn more about transactional messages and `SendEmailRequest` properties](https://customer.io/docs/transactional-api).
201
+ Use `send_email` referencing your request to send a transactional message. [Learn more about transactional messages and `SendEmailRequest` properties](https://customer.io/docs/journeys/transactional-api).
203
202
 
204
203
  ```python
205
204
  from customerio import APIClient, Regions, SendEmailRequest
@@ -207,6 +206,7 @@ client = APIClient("your API key", region=Regions.US)
207
206
 
208
207
  request = SendEmailRequest(
209
208
  to="person@example.com",
209
+ _from="override.sender@example.com",
210
210
  transactional_message_id="3",
211
211
  message_data={
212
212
  "name": "person",
@@ -222,7 +222,7 @@ request = SendEmailRequest(
222
222
  }
223
223
  )
224
224
 
225
- with open("path to file", "rb") as f:
225
+ with open("receipt.pdf", "rb") as f:
226
226
  request.attach('receipt.pdf', f.read())
227
227
 
228
228
  response = client.send_email(request)
@@ -235,7 +235,7 @@ SendPushRequest requires:
235
235
  * `transactional_message_id`: the ID of the transactional push message you want to send.
236
236
  * an `identifiers` object containing the `id` or `email` of your recipient. If the profile does not exist, Customer.io will create it.
237
237
 
238
- Use `send_push` referencing your request to send a transactional message. [Learn more about transactional messages and `SendPushRequest` properties](https://customer.io/docs/transactional-api).
238
+ Use `send_push` referencing your request to send a transactional message. [Learn more about transactional messages and `SendPushRequest` properties](https://customer.io/docs/journeys/transactional-api).
239
239
 
240
240
  ```python
241
241
  from customerio import APIClient, Regions, SendPushRequest
@@ -2,5 +2,5 @@ import warnings
2
2
 
3
3
  from customerio.client_base import CustomerIOException
4
4
  from customerio.track import CustomerIO
5
- from customerio.api import APIClient, SendEmailRequest, SendPushRequest
5
+ from customerio.api import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest
6
6
  from customerio.regions import Regions
@@ -1,4 +1,4 @@
1
- VERSION = (2, 1, 0, 'final', 0)
1
+ VERSION = (2, 2, 0, 'final', 0)
2
2
 
3
3
  def get_version():
4
4
  version = '%s.%s' % (VERSION[0], VERSION[1])
@@ -27,6 +27,12 @@ class APIClient(ClientBase):
27
27
  request = request._to_dict()
28
28
  resp = self.send_request('POST', self.url + "/v1/send/push", request)
29
29
  return json.loads(resp)
30
+
31
+ def send_sms(self, request):
32
+ if isinstance(request, SendSMSRequest):
33
+ request = request._to_dict()
34
+ resp = self.send_request('POST', self.url + "/v1/send/sms", request)
35
+ return json.loads(resp)
30
36
 
31
37
  # builds the session.
32
38
  def _build_session(self):
@@ -211,3 +217,50 @@ class SendPushRequest(object):
211
217
  data[name] = value
212
218
 
213
219
  return data
220
+
221
+ class SendSMSRequest(object):
222
+ '''An object with all the options avaiable for triggering a transactional push message'''
223
+ def __init__(self,
224
+ transactional_message_id=None,
225
+ to=None,
226
+ identifiers=None,
227
+ disable_message_retention=None,
228
+ send_to_unsubscribed=None,
229
+ queue_draft=None,
230
+ message_data=None,
231
+ send_at=None,
232
+ language=None,
233
+ ):
234
+
235
+ self.transactional_message_id = transactional_message_id
236
+ self.to = to
237
+ self.identifiers = identifiers
238
+ self.disable_message_retention = disable_message_retention
239
+ self.send_to_unsubscribed = send_to_unsubscribed
240
+ self.queue_draft = queue_draft
241
+ self.message_data = message_data
242
+ self.send_at = send_at
243
+ self.language = language
244
+
245
+ def _to_dict(self):
246
+ '''Build a request payload from the object'''
247
+ field_map = dict(
248
+ # field name is the same as the payload field name
249
+ transactional_message_id="transactional_message_id",
250
+ to="to",
251
+ identifiers="identifiers",
252
+ disable_message_retention="disable_message_retention",
253
+ send_to_unsubscribed="send_to_unsubscribed",
254
+ queue_draft="queue_draft",
255
+ message_data="message_data",
256
+ send_at="send_at",
257
+ language="language",
258
+ )
259
+
260
+ data = {}
261
+ for field, name in field_map.items():
262
+ value = getattr(self, field, None)
263
+ if value is not None:
264
+ data[name] = value
265
+
266
+ return data
@@ -1,12 +1,11 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: customerio
3
- Version: 2.1
3
+ Version: 2.2
4
4
  Summary: Customer.io Python bindings.
5
5
  Home-page: https://github.com/customerio/customerio-python
6
6
  Author: Peaberry Software Inc.
7
7
  Author-email: support@customerio.com
8
8
  License: BSD
9
- Platform: UNKNOWN
10
9
  Classifier: Environment :: Web Environment
11
10
  Classifier: Intended Audience :: Developers
12
11
  Classifier: License :: OSI Approved :: BSD License
@@ -18,6 +17,3 @@ Classifier: Programming Language :: Python :: 3.8
18
17
  Classifier: Programming Language :: Python :: 3.9
19
18
  License-File: LICENSE
20
19
  License-File: AUTHORS
21
-
22
- UNKNOWN
23
-
@@ -3,7 +3,6 @@ try:
3
3
  except ImportError:
4
4
  from http.server import BaseHTTPRequestHandler, HTTPServer
5
5
 
6
- from functools import wraps
7
6
  from random import randint
8
7
  import json
9
8
  import ssl
@@ -11,12 +10,11 @@ import time
11
10
  import threading
12
11
  import unittest
13
12
 
14
- def sslwrap(func):
15
- @wraps(func)
16
- def bar(*args, **kw):
17
- kw['ssl_version'] = ssl.PROTOCOL_SSLv23
18
- return func(*args, **kw)
19
- return bar
13
+ def create_ssl_context():
14
+ """Create SSL context for Python 3.12+ compatibility"""
15
+ context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER)
16
+ context.minimum_version = ssl.TLSVersion.TLSv1_2
17
+ return context
20
18
 
21
19
  request_counts = dict()
22
20
 
@@ -75,12 +73,11 @@ class HTTPSTestCase(unittest.TestCase):
75
73
  def setUpClass(cls):
76
74
  # create a server
77
75
  cls.server = HTTPServer(("localhost", 0), Handler)
78
- # hack needed to setup ssl server
79
- ssl.wrap_socket = sslwrap(ssl.wrap_socket)
76
+ # create SSL context for Python 3.12+ compatibility
77
+ context = create_ssl_context()
78
+ context.load_cert_chain('./tests/server.pem')
80
79
  # upgrade to https
81
- cls.server.socket = ssl.wrap_socket(cls.server.socket,
82
- certfile='./tests/server.pem',
83
- server_side=True)
80
+ cls.server.socket = context.wrap_socket(cls.server.socket, server_side=True)
84
81
  # start server instance in new thread
85
82
  cls.server_thread = threading.Thread(target=cls.server.serve_forever)
86
83
  cls.server_thread.start()
@@ -5,7 +5,7 @@ import json
5
5
  import sys
6
6
  import unittest
7
7
 
8
- from customerio import APIClient, SendEmailRequest, SendPushRequest, Regions, CustomerIOException
8
+ from customerio import APIClient, SendEmailRequest, SendPushRequest, SendSMSRequest, Regions, CustomerIOException
9
9
  from customerio.__version__ import __version__ as ClientVersion
10
10
  from tests.server import HTTPSTestCase
11
11
 
@@ -95,5 +95,21 @@ class TestAPIClient(HTTPSTestCase):
95
95
 
96
96
  self.client.send_push(push)
97
97
 
98
+ def test_send_sms(self):
99
+ self.client.http.hooks = dict(response=partial(self._check_request, rq={
100
+ 'method': 'POST',
101
+ 'authorization': "Bearer app_api_key",
102
+ 'content_type': 'application/json',
103
+ 'url_suffix': '/v1/send/sms',
104
+ 'body': {"identifiers": {"id":"customer_1"}, "transactional_message_id": 100}
105
+ }))
106
+
107
+ sms = SendSMSRequest(
108
+ identifiers={"id":"customer_1"},
109
+ transactional_message_id=100,
110
+ )
111
+
112
+ self.client.send_sms(sms)
113
+
98
114
  if __name__ == '__main__':
99
115
  unittest.main()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes