Add optional params into subscribe action and Python3 fixes
4 files changed, 94 insertions(+), 67 deletions(-)

M .hgignore
M sendy/api.py
M sendy/binder.py
M setup.py
M .hgignore +2 -0
@@ 9,3 9,5 @@ syntax:glob
 dist/
 *.egg-info/
 *.egg
+env
+.env
  No newline at end of file

          
M sendy/api.py +59 -35
@@ 4,66 4,90 @@ import logging
 
 from .binder import bind_api
 
-
 log = logging.getLogger(__name__)
 
 
-class SendyAPI(object):
-    ''' Class used to map to all Sendy API endpoints
-    '''
+class SendyAPI:
+    """ Class used to map to all Sendy API endpoints
+    """
+
     def __init__(self, host, api_key=None, debug=False):
         self.host = host
-        if self.host[-1] != '/':
-            self.host = '{0}/'.format(self.host)
+        if self.host[-1] != "/":
+            self.host = "{0}/".format(self.host)
         self.api_key = api_key
         self.debug = debug
 
     subscribe = bind_api(
-        path='subscribe',
-        allowed_param=['list', 'email', 'name'],
-        extra_param={'boolean': 'true'},
-        success_message='1',
+        path="subscribe",
+        allowed_param=[
+            "list",
+            "email",
+            "name",
+            "country",
+            "ipaddress",
+            "referrer",
+            "gdpr",
+            "hp",
+        ],
+        extra_param={"boolean": "true"},
+        success_message="1",
         require_auth=False,
-        method='POST',
+        method="POST",
     )
 
     unsubscribe = bind_api(
-        path='unsubscribe',
-        allowed_param=['list', 'email'],
-        extra_param={'boolean': 'true'},
-        success_message='1',
+        path="unsubscribe",
+        allowed_param=["list", "email"],
+        extra_param={"boolean": "true"},
+        success_message="1",
         require_auth=False,
-        method='POST',
+        method="POST",
     )
 
     delete = bind_api(
-        path='api/subscribers/delete.php',
-        allowed_param=['list_id', 'email'],
-        success_message='1',
-        method='POST',
+        path="api/subscribers/delete.php",
+        allowed_param=["list_id", "email"],
+        success_message="1",
+        method="POST",
     )
 
     subscription_status = bind_api(
-        path='api/subscribers/subscription-status.php',
-        allowed_param=['list_id', 'email'],
-        success_message=['Subscribed', 'Unsubscribed', 'Unconfirmed',
-                         'Bounced', 'Soft bounced', 'Complained'],
-        method='POST',
+        path="api/subscribers/subscription-status.php",
+        allowed_param=["list_id", "email"],
+        success_message=[
+            "Subscribed",
+            "Unsubscribed",
+            "Unconfirmed",
+            "Bounced",
+            "Soft bounced",
+            "Complained",
+        ],
+        method="POST",
     )
 
     subscriber_count = bind_api(
-        path='api/subscribers/active-subscriber-count.php',
-        allowed_param=['list_id'],
+        path="api/subscribers/active-subscriber-count.php",
+        allowed_param=["list_id"],
         success_message=int,
-        method='POST',
+        method="POST",
     )
 
     create_campaign = bind_api(
-        path='api/campaigns/create.php',
-        allowed_param=['from_name', 'from_email', 'reply_to', 'title',
-                       'subject', 'plain_text', 'html_text', 'list_ids',
-                       'brand_id', 'query_string', 'send_campaign'],
-        success_message=['Campaign created',
-                         'Campaign created and now sending'],
-        method='POST',
+        path="api/campaigns/create.php",
+        allowed_param=[
+            "from_name",
+            "from_email",
+            "reply_to",
+            "title",
+            "subject",
+            "plain_text",
+            "html_text",
+            "list_ids",
+            "brand_id",
+            "query_string",
+            "send_campaign",
+        ],
+        success_message=["Campaign created", "Campaign created and now sending"],
+        method="POST",
     )

          
M sendy/binder.py +31 -30
@@ 2,12 2,15 @@ from __future__ import unicode_literals
 
 import json
 import logging
+
 import requests
+
+from .exceptions import SendyError
+
 try:
     from urlparse import urljoin
 except ImportError:
     from urllib.parse import urljoin
-from .exceptions import SendyError
 
 
 log = logging.getLogger(__name__)

          
@@ 21,26 24,25 @@ def convert_to_utf8(value):
     if isinstance(value, str):
         value = unicode(value)
     if isinstance(value, unicode):
-        return value.decode('utf-8')
+        return value.decode("utf-8")
     return value
 
 
 def bind_api(**config):
-
-    class APIMethod(object):
-        path = config['path']
-        allowed_param = config.get('allowed_param', [])
-        method = config.get('method', 'GET')
-        require_auth = config.get('require_auth', True)
-        success_status_code = config.get('success_status_code', 200)
-        success_message = config.get('success_message', None)
-        extra_param = config.get('extra_param', None)
-        fail_silently = config.get('fail_silently', True)
+    class APIMethod:
+        path = config["path"]
+        allowed_param = config.get("allowed_param", [])
+        method = config.get("method", "GET")
+        require_auth = config.get("require_auth", True)
+        success_status_code = config.get("success_status_code", 200)
+        success_message = config.get("success_message", None)
+        extra_param = config.get("extra_param", None)
+        fail_silently = config.get("fail_silently", True)
 
         def __init__(self, api, args, kwargs):
             self.api = api
-            self.headers = kwargs.pop('headers', {})
-            self.post_data = kwargs.pop('post_data', None)
+            self.headers = kwargs.pop("headers", {})
+            self.post_data = kwargs.pop("post_data", None)
             self.build_parameters(args, kwargs)
             self.path = self.path.format(**self.parameters)  # Sub any URL vars
             self.host = api.host

          
@@ 55,17 57,16 @@ def bind_api(**config):
                     continue
 
                 try:
-                    self.parameters[self.allowed_param[idx]] = \
-                                                    convert_to_utf8(arg)
+                    self.parameters[self.allowed_param[idx]] = convert_to_utf8(arg)
                 except IndexError:
-                    raise ValueError('Too many parameters supplied!')
+                    raise ValueError("Too many parameters supplied!")
 
             for k, arg in kwargs.items():
                 if arg is None:
                     continue
                 if k in self.parameters:
                     raise ValueError(
-                        'Multiple values for parameter {0} supplied!'.format(k)
+                        "Multiple values for parameter {0} supplied!".format(k)
                     )
 
                 self.parameters[k] = convert_to_utf8(arg)

          
@@ 74,25 75,23 @@ def bind_api(**config):
                 self.parameters.update(self.extra_param)
 
             if self.require_auth and self.api.api_key is not None:
-                self.parameters['api_key'] = self.api.api_key
+                self.parameters["api_key"] = self.api.api_key
+
+            print(self.parameters)
 
         def execute(self):
             # Build the request URL
             url = urljoin(self.host, self.path)
 
             if self.api.debug:
-                log.info('* Sending {0}: {1}\nHeaders: {2}\nData:{3}'.format(
-                    self.method,
-                    url,
-                    self.headers,
-                    self.post_data,
-                ))
+                log.info(
+                    "* Sending {0}: {1}\nHeaders: {2}\nData:{3}".format(
+                        self.method, url, self.headers, self.post_data
+                    )
+                )
 
             response = requests.request(
-                self.method,
-                url,
-                headers=self.headers,
-                data=self.parameters,
+                self.method, url, headers=self.headers, data=self.parameters
             )
             data = response.content
             if callable(self.success_message):

          
@@ 103,11 102,13 @@ def bind_api(**config):
                         raise SendyError(data)
 
             success = data in self.success_message
+            print(self.success_message)
             if not success and not self.fail_silently:
+                print("Error")
+                print(data)
                 raise SendyError(data)
             return data
 
-
     def _call(api, *args, **kwargs):
         method = APIMethod(api, args, kwargs)
         return method.execute()

          
M setup.py +2 -2
@@ 18,14 18,14 @@ setup(
     url='https://bitbucket.org/netlandish/sendypy/',
     long_description=long_description,
     platforms=['any'],
-    install_requires=['requests>=2.6.0'],
+    install_requires=['requests>=2.19.1'],
     classifiers=[
         'Development Status :: 4 - Beta',
         'Intended Audience :: Developers',
         'Natural Language :: English',
         'Operating System :: OS Independent',
         'Programming Language :: Python',
-        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3.7.0',
         'Environment :: Web Environment',
     ],
     include_package_data=True,