Skip to content

Commit

Permalink
3.x compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
kirill-konshin committed Feb 7, 2017
1 parent a9b2790 commit 2d721dd
Show file tree
Hide file tree
Showing 15 changed files with 169 additions and 73 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,5 +1,6 @@
*.pyc
.coverage
.ve
_cache
credentials.ini
dist
13 changes: 12 additions & 1 deletion Makefile
Expand Up @@ -32,4 +32,15 @@ register:

.PHONY: register-test
register-test:
python setup.py register -r pypitest
python setup.py register -r pypitest

.PHONY: install-ve
install-ve:
virtualenv --python `which python3` .ve
.ve/bin/pip install -r requirements.txt
.ve/bin/pip install -r requirements-dev.txt
.ve/bin/pip install configparser

.PHONY: test-ve
test-ve:
.ve/bin/python -m unittest discover . --pattern '*test.py'
94 changes: 54 additions & 40 deletions demo.py
Expand Up @@ -2,16 +2,26 @@
# encoding: utf-8

import os
import sys
import json
import ConfigParser
from multiprocessing import Process
from time import sleep
from ringcentral.subscription import Events
from ringcentral.http.api_exception import ApiException
from ringcentral import SDK


config = ConfigParser.ConfigParser()
def get_config_parser():
if sys.version_info[0] == 3:
from configparser import ConfigParser
return ConfigParser
else:
import ConfigParser
return ConfigParser.ConfigParser


ConfigParser = get_config_parser()
config = ConfigParser()
config.read('credentials.ini')

USERNAME = config.get('Credentials', 'USERNAME')
Expand Down Expand Up @@ -72,44 +82,48 @@ def main():
print('User loaded ' + user.name + ' (' + user_id + ')')
print('Headers ' + str(response.response().headers))

# Multipart response
try:
multipart_response = platform.get('/account/~/extension/' + user_id + ',' + user_id + '/presence').multipart()
print 'Multipart 1\n' + str(multipart_response[0].json_dict())
print 'Multipart 2\n' + str(multipart_response[1].json_dict())
except ApiException as e:
print 'Cannot load multipart'
print 'URL ' + e.api_response().request().url
print 'Response' + str(e.api_response().json())

# Pubnub notifications example
def on_message(msg):
print(msg)

def pubnub():
try:
s = sdk.create_subscription()
s.add_events(['/account/~/extension/~/message-store'])
s.on(Events.notification, on_message)
s.register()

while True:
sleep(0.1)

except KeyboardInterrupt:
print("Pubnub listener stopped...")

p = Process(target=pubnub)
try:
p.start()
except KeyboardInterrupt:
p.terminate()
print("Stopped by User")

set_file_cache(platform.auth().data())
print("Authentication data has been cached")

print("Wait for notification...")
print(type(response.response()._content))

return False

# # Multipart response
# try:
# multipart_response = platform.get('/account/~/extension/' + user_id + ',' + user_id + '/presence').multipart()
# print 'Multipart 1\n' + str(multipart_response[0].json_dict())
# print 'Multipart 2\n' + str(multipart_response[1].json_dict())
# except ApiException as e:
# print 'Cannot load multipart'
# print 'URL ' + e.api_response().request().url
# print 'Response' + str(e.api_response().json())
#
# # Pubnub notifications example
# def on_message(msg):
# print(msg)
#
# def pubnub():
# try:
# s = sdk.create_subscription()
# s.add_events(['/account/~/extension/~/message-store'])
# s.on(Events.notification, on_message)
# s.register()
#
# while True:
# sleep(0.1)
#
# except KeyboardInterrupt:
# print("Pubnub listener stopped...")
#
# p = Process(target=pubnub)
# try:
# p.start()
# except KeyboardInterrupt:
# p.terminate()
# print("Stopped by User")
#
# set_file_cache(platform.auth().data())
# print("Authentication data has been cached")
#
# print("Wait for notification...")


if __name__ == '__main__':
Expand Down
42 changes: 42 additions & 0 deletions ringcentral/core/__init__.py
@@ -0,0 +1,42 @@
import urllib
import base64
import sys
import re


def is_third():
return sys.version_info >= (3, 0)


def urlencode(s):
if hasattr(urllib, 'urlencode'):
return urllib.urlencode(s)
elif hasattr(urllib, 'parse'):
return urllib.parse.urlencode(s)
else:
raise Exception("No urlencode")


def iterator(thing):
return thing.iteritems() if hasattr(thing, 'iteritems') else iter(thing.items())


def base64encode(s):
if is_third():
return str(base64.b64encode(bytes(s, 'utf8')), 'utf8')
else:
return base64.b64encode(s)


def tostr(s):
if is_third():
return str(s, 'utf8')
else:
return str(s)


def clean_decrypted(s):
if is_third():
return re.sub(r"[\u0001-\u0010]", '', s).strip()
else:
return s.replace('\x05', '')
2 changes: 1 addition & 1 deletion ringcentral/http/api_exception.py
Expand Up @@ -6,7 +6,7 @@ class ApiException(Exception):
def __init__(self, apiResponse, previous=None):
self.__apiResponse = apiResponse

message = previous.message if previous else 'Unknown error'
message = previous.message if previous and hasattr(previous, 'message') else 'Unknown error'
status = 0 # previous.status if previous else 0

if apiResponse:
Expand Down
20 changes: 15 additions & 5 deletions ringcentral/http/api_response.py
Expand Up @@ -4,6 +4,7 @@
import requests
from email.feedparser import FeedParser
from .json_object import *
from ..core import is_third


class ApiResponse:
Expand Down Expand Up @@ -39,7 +40,7 @@ def multipart(self):
parts = self._break_into_parts()

if len(parts) < 1:
raise Exception("Malformed Batch Response (not enough parts)") # sic! not specific extension
raise Exception("Malformed Batch Response (not enough parts)") # sic! not specific extension

statuses = json.loads(parts[0].get_payload())

Expand All @@ -49,10 +50,7 @@ def multipart(self):
responses = []

for response, payload in zip(statuses["response"], parts[1:]):
res = requests.Response()
res.headers = dict(payload)
res._content = str(payload.get_payload())
res.status_code = response["status"]
res = create_response(payload, response['status'])

responses.append(ApiResponse(response=res))

Expand Down Expand Up @@ -106,3 +104,15 @@ def _break_into_parts(self):
parts = msg.get_payload()

return parts


def create_response(payload, status):
res = requests.Response()
res.headers = dict(payload)
if is_third():
res._content = bytes(payload.get_payload(), 'utf8')
res.encoding = 'utf8'
else:
res._content = str(payload.get_payload())
res.status_code = status
return res
10 changes: 8 additions & 2 deletions ringcentral/http/api_response_test.py
Expand Up @@ -4,7 +4,8 @@
import unittest

from ..test import TestCase
from api_response import ApiResponse
from ..core import is_third
from .api_response import ApiResponse
from requests import Response

multipart_headers = {'Content-Type': 'multipart/mixed; boundary=Boundary_1245_945802293_1394135045248'}
Expand Down Expand Up @@ -106,10 +107,15 @@ def test_multipart_bad_response(self):
r.multipart()


# FIXME Use create response from main file api_response
def create_response(body, status, headers=None):
res = Response()
res.headers = headers
res._content = body
if is_third():
res._content = bytes(body, 'utf8')
res.encoding = 'utf8'
else:
res._content = body
res.status_code = status
return res

Expand Down
12 changes: 7 additions & 5 deletions ringcentral/http/client.py
Expand Up @@ -6,6 +6,7 @@

from .api_response import ApiResponse
from .api_exception import ApiException
from ..core import urlencode, iterator


class Client:
Expand All @@ -30,7 +31,6 @@ def send(self, request):
raise ApiException(response, e)

def load_response(self, request):

# TODO Persist between requests?
session = None

Expand All @@ -57,7 +57,7 @@ def create_request(self, method='', url='', query_params=None, body=None, header
"""

if query_params:
query = urllib.urlencode(query_params)
query = urlencode(query_params)
if query:
url = url + ('&' if url.find('?') > 0 else '?') + query

Expand All @@ -67,7 +67,9 @@ def create_request(self, method='', url='', query_params=None, body=None, header
if headers is None:
headers = {}

for key, value in headers.iteritems():
it = iterator(headers)

for key, value in it:
if key.lower().find('content-type') >= 0:
content_type = value
if key.lower().find('accept') >= 0:
Expand All @@ -82,8 +84,8 @@ def create_request(self, method='', url='', query_params=None, body=None, header
headers['Accept'] = accept

if content_type.lower().find('application/json') >= 0:
body = json.dumps(body)
body = json.dumps(body) if body else None
elif content_type.lower().find('application/x-www-form-urlencoded') >= 0:
body = urllib.urlencode(body)
body = urlencode(body) if body else None

return requests.Request(method, url, headers=headers, data=body)
8 changes: 4 additions & 4 deletions ringcentral/http/client_test.py
Expand Up @@ -16,19 +16,19 @@ def test_create_request_with_query_string(self):

def test_create_request_encode_body_url(self):
r = Client().create_request(body=body, headers={'Content-Type': 'application/x-www-form-urlencoded'})
self.assertEquals('foo=bar&baz=qux', r.data)
self.assertEqual('foo=bar&baz=qux', r.data)

def test_create_request_encode_body_json(self):
r = Client().create_request(body=body, headers={'Content-Type': 'application/json'})
self.assertEquals('{"foo": "bar", "baz": "qux"}', r.data)
self.assertEqual('{"foo": "bar", "baz": "qux"}', r.data)

def test_create_request_encode_body_json_default(self):
r = Client().create_request(body=body) # JSON by default
self.assertEquals('{"foo": "bar", "baz": "qux"}', r.data)
self.assertEqual('{"foo": "bar", "baz": "qux"}', r.data)

def test_create_request_encode_body_alternative(self):
r = Client().create_request(body='foo-encoded-text', headers={'content-type': 'foo'})
self.assertEquals('foo-encoded-text', r.data)
self.assertEqual('foo-encoded-text', r.data)


if __name__ == '__main__':
Expand Down
4 changes: 3 additions & 1 deletion ringcentral/http/json_object.py
@@ -1,5 +1,7 @@
# !/usr/bin/env python
# encoding: utf-8
from ..core import iterator


PYTHON_KEYWORDS = (
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with", "assert", "else", "if", "pass", "yield",
Expand All @@ -22,7 +24,7 @@ def safe_name(n):
def unfold(d):
if isinstance(d, dict):
o = JsonObject()
for k, v in d.iteritems():
for k, v in iterator(d):
o.__dict__[safe_name(k)] = unfold(v)
return o
elif isinstance(d, list):
Expand Down
4 changes: 2 additions & 2 deletions ringcentral/platform/platform.py
@@ -1,9 +1,9 @@
#!/usr/bin/env python
# encoding: utf-8

import base64
import sys
from .auth import Auth
from ..core import base64encode

ACCOUNT_ID = '~'
ACCOUNT_PREFIX = '/account/'
Expand Down Expand Up @@ -139,7 +139,7 @@ def _request_token(self, path='', body=None):
return self.send_request(request, skip_auth_check=True)

def _api_key(self):
return base64.b64encode(self._key + ':' + self._secret)
return base64encode(self._key + ':' + self._secret)

def _auth_header(self):
return self._auth.token_type() + ' ' + self._auth.access_token()
Expand Down
2 changes: 1 addition & 1 deletion ringcentral/platform/platform_test.py
Expand Up @@ -35,7 +35,7 @@ def test_refresh_with_outdated_token(self, mock):
sdk.platform().refresh()
except Exception as e:
caught = True
self.assertEqual('Refresh token has expired', e.message)
self.assertEqual('Refresh token has expired', str(e))

self.assertTrue(caught)

Expand Down
1 change: 1 addition & 0 deletions ringcentral/subscription/events.py
Expand Up @@ -2,6 +2,7 @@
# encoding: utf-8

class Events:
connectionError = 'connectionError'
notification = 'notification'
subscribeSuccess = 'subscribeSuccess'
subscribeError = 'subscribeError'
Expand Down

0 comments on commit 2d721dd

Please sign in to comment.