From 62edaf064d1d643f7a2112ebe7ff2050734adb93 Mon Sep 17 00:00:00 2001 From: Volodymyr Hotsyk Date: Thu, 24 Jul 2014 19:23:56 +0200 Subject: [PATCH] Port to support both python2 and python3 --- examples/desktop_app.py | 24 +- examples/web_based_app.py | 34 +- getting_started.rst | 6 +- how_to.rst | 14 +- odesk/exceptions.py | 6 +- odesk/http.py | 19 +- odesk/oauth.py | 19 +- odesk/routers/job.py | 6 +- odesk/routers/mc.py | 2 +- odesk/routers/task.py | 10 +- odesk/tests.py | 720 +++++++++++++++++++------------------- odesk/utils.py | 2 + setup.py | 14 +- 13 files changed, 448 insertions(+), 428 deletions(-) diff --git a/examples/desktop_app.py b/examples/desktop_app.py index e7be5b1..aa457bb 100644 --- a/examples/desktop_app.py +++ b/examples/desktop_app.py @@ -1,3 +1,5 @@ +from __future__ import print_function + import odesk from pprint import pprint @@ -9,7 +11,7 @@ def desktop_app(): Returns: ``odesk.Client`` instance ready to work. """ - print "Emulating desktop app" + print("Emulating desktop app") public_key = raw_input('Please enter public key: > ') secret_key = raw_input('Please enter secret key: > ') @@ -20,9 +22,9 @@ def desktop_app(): 'following this link:\n{0}\n\n> '.format( client.auth.get_authorize_url())) - print 'Retrieving keys.... ' + print('Retrieving keys.... ') access_token, access_token_secret = client.auth.get_access_token(verifier) - print 'OK' + print('OK') # For further use you can store ``access_toket`` and # ``access_token_secret`` somewhere @@ -36,19 +38,19 @@ def desktop_app(): client = desktop_app() try: - print "My info" + print("My info") pprint(client.auth.get_info()) - print "Team rooms:" + print("Team rooms:") pprint(client.team.get_teamrooms()) #HRv2 API - print "HR: companies" + print("HR: companies") pprint(client.hr.get_companies()) - print "HR: teams" + print("HR: teams") pprint(client.hr.get_teams()) - print "HR: userroles" + print("HR: userroles") pprint(client.hr.get_user_roles()) - print "Get jobs" + print("Get jobs") pprint(client.provider.search_jobs({'q': 'python'})) - except Exception, e: - print "Exception at %s %s" % (client.last_method, client.last_url) + except Exception as e: + print("Exception at %s %s" % (client.last_method, client.last_url)) raise e diff --git a/examples/web_based_app.py b/examples/web_based_app.py index 9256de3..8e44e6d 100644 --- a/examples/web_based_app.py +++ b/examples/web_based_app.py @@ -1,4 +1,6 @@ +from __future__ import print_function import odesk +from six import input from pprint import pprint @@ -9,20 +11,20 @@ def web_based_app(): Returns: ``odesk.Client`` instance ready to work. """ - print "Emulating web-based app" + print("Emulating web-based app") - public_key = raw_input('Please enter public key: > ') - secret_key = raw_input('Please enter secret key: > ') + public_key = input('Please enter public key: > ') + secret_key = input('Please enter secret key: > ') #Instantiating a client without an auth token client = odesk.Client(public_key, secret_key) - print "Please to this URL (authorize the app if necessary):" - print client.auth.get_authorize_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?oauth_verifier= parameter" + print("Please to this URL (authorize the app if necessary):") + print(client.auth.get_authorize_url()) + print("After that you should be redirected back to your app URL with " + "additional ?oauth_verifier= parameter") - verifier = raw_input('Enter oauth_verifier: ') + verifier = input('Enter oauth_verifier: ') oauth_access_token, oauth_access_token_secret = \ client.auth.get_access_token(verifier) @@ -42,19 +44,19 @@ def web_based_app(): client = web_based_app() try: - print "My info" + print("My info") pprint(client.auth.get_info()) - print "Team rooms:" + print("Team rooms:") pprint(client.team.get_teamrooms()) #HRv2 API - print "HR: companies" + print("HR: companies") pprint(client.hr.get_companies()) - print "HR: teams" + print("HR: teams") pprint(client.hr.get_teams()) - print "HR: userroles" + print("HR: userroles") pprint(client.hr.get_user_roles()) - print "Get jobs" + print("Get jobs") pprint(client.provider.search_jobs({'q': 'python'})) - except Exception, e: - print "Exception at %s %s" % (client.last_method, client.last_url) + except Exception as e: + print("Exception at %s %s" % (client.last_method, client.last_url)) raise e diff --git a/getting_started.rst b/getting_started.rst index 215ca18..7b64877 100644 --- a/getting_started.rst +++ b/getting_started.rst @@ -76,7 +76,7 @@ Initializing the client:: Now follow the ``authorize_url``:: - print client.auth.get_authorize_url() + print(client.auth.get_authorize_url()) After you follow this url you'll be redirected to the callback url that you entered during API keys creation. The ``oauth_verifier`` parameter is passed to the callback @@ -107,11 +107,11 @@ This call will give you information about the currently authorized user. So now just start playing with the API, for example you can get your teamrooms:: - print client.team.get_teamrooms() + print(client.team.get_teamrooms()) or get your companies:: - print client.hr.get_companies() + print(client.hr.get_companies()) See the Reference Documentation for the full list of available API calls diff --git a/how_to.rst b/how_to.rst index 9c60c27..82cb18e 100644 --- a/how_to.rst +++ b/how_to.rst @@ -26,18 +26,18 @@ http://developers.odesk.com/Authentication To authenticate your web application with the python-odesk, use something similar to the code below:: - public_key = raw_input('Please enter public key: > ') - secret_key = raw_input('Please enter secret key: > ') + public_key = input('Please enter public key: > ') + secret_key = input('Please enter secret key: > ') #Instantiating a client without an auth token client = odesk.Client(public_key, secret_key) - print "Please to this URL (authorize the app if necessary):" - print client.auth.get_authorize_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?oauth_verifier= parameter" + print("Please to this URL (authorize the app if necessary):") + print(client.auth.get_authorize_url()) + print("After that you should be redirected back to your app URL with " + "additional ?oauth_verifier= parameter") - verifier = raw_input('Enter oauth_verifier: ') + verifier = input('Enter oauth_verifier: ') oauth_access_token, oauth_access_token_secret = \ client.auth.get_access_token(verifier) diff --git a/odesk/exceptions.py b/odesk/exceptions.py index ea132d8..33c255f 100644 --- a/odesk/exceptions.py +++ b/odesk/exceptions.py @@ -3,7 +3,7 @@ # (C) 2010-2014 oDesk import logging -import urllib2 +from six.moves import urllib class BaseException(Exception): @@ -19,10 +19,10 @@ def odesk_debug(self, *args, **kwargs): logger = logging.getLogger('python-odesk') logger.debug('{0}: {1}'.format( self.__class__.__name__, - ', '.join(map(unicode, args)))) + ', '.join(map(str, args)))) -class BaseHttpException(urllib2.HTTPError, BaseException): +class BaseHttpException(urllib.error.HTTPError, BaseException): def __init__(self, *args, **kwargs): self.odesk_debug(*args, **kwargs) diff --git a/odesk/http.py b/odesk/http.py index fe60673..eed7a7f 100644 --- a/odesk/http.py +++ b/odesk/http.py @@ -3,8 +3,7 @@ # (C) 2010-2014 oDesk import logging -import urllib2 -import httplib +from six.moves import http_client, urllib from odesk.exceptions import HTTP400BadRequestError, HTTP401UnauthorizedError,\ HTTP403ForbiddenError, HTTP404NotFoundError @@ -17,12 +16,12 @@ def raise_http_error(url, response): - """Raise custom ``urllib2.HTTPError`` exception. + """Raise custom ``urllib.error.HTTPError`` exception. *Parameters:* :url: Url that caused an error - :response: ``urllib3`` response object + :response: ``urllib`` response object """ status_code = response.status @@ -34,21 +33,21 @@ def raise_http_error(url, response): formatted_msg = 'Code {0}: {1}'.format(odesk_error_code, odesk_error_message) - if status_code == httplib.BAD_REQUEST: + if status_code == http_client.BAD_REQUEST: raise HTTP400BadRequestError(url, status_code, formatted_msg, headers, None) - elif status_code == httplib.UNAUTHORIZED: + elif status_code == http_client.UNAUTHORIZED: raise HTTP401UnauthorizedError(url, status_code, formatted_msg, headers, None) - elif status_code == httplib.FORBIDDEN: + elif status_code == http_client.FORBIDDEN: raise HTTP403ForbiddenError(url, status_code, formatted_msg, headers, None) - elif status_code == httplib.NOT_FOUND: + elif status_code == http_client.NOT_FOUND: raise HTTP404NotFoundError(url, status_code, formatted_msg, headers, None) else: - error = urllib2.HTTPError(url, status_code, formatted_msg, - headers, None) + error = urllib.error.HTTPError(url, status_code, formatted_msg, + headers, None) logger = logging.getLogger('python-odesk') logger.debug(str(error)) raise error diff --git a/odesk/oauth.py b/odesk/oauth.py index e292de2..c29d9f8 100644 --- a/odesk/oauth.py +++ b/odesk/oauth.py @@ -2,12 +2,11 @@ # python-odesk version 0.5 # (C) 2010-2014 oDesk +from six.moves import urllib +import logging +import oauth2 as oauth import os import time -import urlparse -import urllib -import oauth2 as oauth -import logging from .config import BASE_URL @@ -91,7 +90,7 @@ def get_request_token(self): if response.get('status') != '200': raise Exception( "Invalid request token response: {0}.".format(content)) - request_token = dict(urlparse.parse_qsl(content)) + request_token = dict(urllib.parse.parse_qsl(content)) self.request_token = request_token.get('oauth_token') self.request_token_secret = request_token.get('oauth_token_secret') return self.request_token, self.request_token_secret @@ -103,10 +102,10 @@ def get_authorize_url(self, callback_url=None): oauth_token = getattr(self, 'request_token', None) or\ self.get_request_token()[0] if callback_url: - params = urllib.urlencode({'oauth_token': oauth_token,\ - 'oauth_callback': callback_url}) + params = urllib.parse.urlencode({'oauth_token': oauth_token, + 'oauth_callback': callback_url}) else: - params = urllib.urlencode({'oauth_token': oauth_token}) + params = urllib.parse.urlencode({'oauth_token': oauth_token}) return '{0}?{1}'.format(self.authorize_url, params) def get_access_token(self, verifier): @@ -116,7 +115,7 @@ def get_access_token(self, verifier): try: request_token = self.request_token request_token_secret = self.request_token_secret - except AttributeError, e: + except AttributeError as e: logger = logging.getLogger('python-odesk') logger.debug(e) raise Exception("At first you need to call get_authorize_url") @@ -127,7 +126,7 @@ def get_access_token(self, verifier): if response.get('status') != '200': raise Exception( "Invalid access token response: {0}.".format(content)) - access_token = dict(urlparse.parse_qsl(content)) + access_token = dict(urllib.parse.parse_qsl(content)) self.access_token = access_token.get('oauth_token') self.access_token_secret = access_token.get('oauth_token_secret') return self.access_token, self.access_token_secret diff --git a/odesk/routers/job.py b/odesk/routers/job.py index cd15728..ae9185f 100644 --- a/odesk/routers/job.py +++ b/odesk/routers/job.py @@ -2,6 +2,8 @@ # python-odesk version 0.5 # (C) 2010-2014 oDesk +from six import u + from odesk.namespaces import Namespace @@ -26,7 +28,7 @@ def get_job_profile(self, job_key): max_keys = 20 url = 'jobs/{0}' # Check job key(s) - if not job_key.__class__ in [str, int, list, tuple]: + if not job_key.__class__ in [str, u, int, list, tuple]: raise ValueError( 'Invalid job key. Job recno, key or list of keys expected, ' + '{0} given'.format(job_key.__class__)) @@ -35,7 +37,7 @@ def get_job_profile(self, job_key): raise ValueError( 'Number of keys per request is limited by {0}'.format( max_keys)) - elif filter(lambda x: not str(x).startswith('~~'), job_key): + elif list(filter(lambda x: not str(x).startswith('~~'), job_key)): raise ValueError( 'List should contain only job keys not recno.') else: diff --git a/odesk/routers/mc.py b/odesk/routers/mc.py index ffb810c..132296e 100644 --- a/odesk/routers/mc.py +++ b/odesk/routers/mc.py @@ -2,7 +2,7 @@ # python-odesk version 0.5 # (C) 2010-2014 oDesk -import urllib +from six.moves import urllib from odesk.namespaces import Namespace diff --git a/odesk/routers/task.py b/odesk/routers/task.py index aaf0ba9..a9fecdd 100644 --- a/odesk/routers/task.py +++ b/odesk/routers/task.py @@ -2,7 +2,7 @@ # python-odesk version 0.5 # (C) 2010-2014 oDesk -import urllib +from six.moves import urllib from odesk.namespaces import Namespace @@ -78,7 +78,7 @@ def get_team_specific_tasks(self, company_id, team_id, task_codes): """ task_codes = self._encode_task_codes(task_codes) url = 'tasks/companies/{0}/teams/{1}/tasks/{2}'.format( - company_id, team_id, urllib.quote(task_codes)) + company_id, team_id, urllib.parse.quote(task_codes)) result = self.get(url) try: return result["tasks"] or [] @@ -227,7 +227,7 @@ def put_team_task(self, company_id, team_id, code, description, url, """ put_url = 'tasks/companies/{0}/teams/{1}/tasks/{2}'.format( - company_id, team_id, urllib.quote(str(code))) + company_id, team_id, urllib.parse.quote(str(code))) data = {'code': code, 'description': description, 'url': url} @@ -295,7 +295,7 @@ def archive_team_task(self, company_id, team_id, task_code): """ url = 'tasks/companies/{0}/teams/{1}/archive/{2}'.format( - company_id, team_id, urllib.quote(str(task_code))) + company_id, team_id, urllib.parse.quote(str(task_code))) return self.put(url, data={}) def archive_company_task(self, company_id, task_code): @@ -328,7 +328,7 @@ def unarchive_team_task(self, company_id, team_id, task_code): """ url = 'tasks/companies/{0}/teams/{1}/unarchive/{2}'.format( - company_id, team_id, urllib.quote(str(task_code))) + company_id, team_id, urllib.parse.quote(str(task_code))) return self.put(url, data={}) def unarchive_company_task(self, company_id, task_code): diff --git a/odesk/tests.py b/odesk/tests.py index 2575701..2be2070 100644 --- a/odesk/tests.py +++ b/odesk/tests.py @@ -23,9 +23,8 @@ from nose.tools import eq_, ok_ from mock import Mock, patch -import urlparse -import urllib2 -import httplib +from six.moves import urllib +from six.moves import http_client try: import json @@ -38,21 +37,21 @@ def __init__(self, **kwargs): self.__dict__.update(kwargs) -sample_json_dict = {u'glossary': - {u'GlossDiv': - {u'GlossList': - {u'GlossEntry': - {u'GlossDef': - {u'GlossSeeAlso': [u'GML', u'XML'], - u'para': u'A meta-markup language'}, - u'GlossSee': u'markup', - u'Acronym': u'SGML', - u'GlossTerm': u'Standard Generalized Markup Language', - u'Abbrev': u'ISO 8879:1986', - u'SortAs': u'SGML', - u'ID': u'SGML'}}, - u'title': u'S'}, - u'title': u'example glossary'}} +sample_json_dict = {'glossary': + {'GlossDiv': + {'GlossList': + {'GlossEntry': + {'GlossDef': + {'GlossSeeAlso': ['GML', 'XML'], + 'para': 'A meta-markup language'}, + 'GlossSee': 'markup', + 'Acronym': 'SGML', + 'GlossTerm': 'Standard Generalized Markup Language', + 'Abbrev': 'ISO 8879:1986', + 'SortAs': 'SGML', + 'ID': 'SGML'}}, + 'title': 'S'}, + 'title': 'example glossary'}} def patched_urlopen(*args, **kwargs): @@ -65,46 +64,50 @@ def test_client_urlopen(): secret_key = 'secret' client = Client(public_key, secret_key, - oauth_access_token='some access token', - oauth_access_token_secret='some access token secret') + oauth_access_token='some access token', + oauth_access_token_secret='some access token secret') #test urlopen data = [{'url': 'http://test.url', 'data': {'foo': 'bar'}, 'method': 'GET', 'result_data': None, - 'result_url': 'http://test.url?api_sig=ddbf4b10a47ca8300554441dc7c9042b&api_key=public&foo=bar', + 'result_url': 'http://test.url?api_sig=ddbf4b10a47ca8300554441dc' + '7c9042b&api_key=public&foo=bar', 'result_method': 'GET'}, - {'url': 'http://test.url', + {'url': 'http://test.url', 'data': {}, 'method': 'POST', - 'result_data': 'api_sig=ba343f176db8166c4b7e88911e7e46ec&api_key=public', + 'result_data': 'api_sig=ba343f176db8166c4b7e88911e7e' + '46ec&api_key=public', 'result_url': 'http://test.url', 'result_method': 'POST'}, - {'url': 'http://test.url', + {'url': 'http://test.url', 'data': {}, 'method': 'PUT', - 'result_data': 'api_sig=52cbaea073a5d47abdffc7fc8ccd839b&api_key=public&http_method=put', + 'result_data': 'api_sig=52cbaea073a5d47abdffc7fc8ccd839b&' + 'api_key=public&http_method=put', 'result_url': 'http://test.url', 'result_method': 'POST'}, - {'url': 'http://test.url', + {'url': 'http://test.url', 'data': {}, 'method': 'DELETE', - 'result_data': 'api_sig=8621f072b1492fbd164d808307ba72b9&api_key=public&http_method=delete', + 'result_data': 'api_sig=8621f072b1492fbd164d808307ba72b9&' + 'api_key=public&http_method=delete', 'result_url': 'http://test.url', 'result_method': 'POST'}, - ] + ] result_json = json.dumps(sample_json_dict) for params in data: result = client.urlopen(url=params['url'], - data=params['data'], - method=params['method']) + data=params['data'], + method=params['method']) assert result.data == result_json, (result.data, result_json) -def patched_urlopen_error(method, url, code=httplib.BAD_REQUEST, +def patched_urlopen_error(method, url, code=http_client.BAD_REQUEST, message=None, data=None, **kwargs): getheaders = Mock() getheaders.return_value = {ODESK_ERROR_CODE: code, @@ -113,37 +116,37 @@ def patched_urlopen_error(method, url, code=httplib.BAD_REQUEST, def patched_urlopen_incorrect_json(self, method, url, **kwargs): - return patched_urlopen_error( - method, url, code=httplib.OK, data='Service temporarily unavailable') + return patched_urlopen_error(method, url, code=http_client.OK, + data='Service temporarily unavailable') def patched_urlopen_400(self, method, url, **kwargs): return patched_urlopen_error( - method, url, code=httplib.BAD_REQUEST, + method, url, code=http_client.BAD_REQUEST, message='Limit exceeded', **kwargs) def patched_urlopen_401(self, method, url, **kwargs): return patched_urlopen_error( - method, url, code=httplib.UNAUTHORIZED, + method, url, code=http_client.UNAUTHORIZED, message='Not authorized', **kwargs) def patched_urlopen_403(self, method, url, **kwargs): return patched_urlopen_error( - method, url, code=httplib.FORBIDDEN, + method, url, code=http_client.FORBIDDEN, message='Forbidden', **kwargs) def patched_urlopen_404(self, method, url, **kwargs): return patched_urlopen_error( - method, url, code=httplib.NOT_FOUND, + method, url, code=http_client.NOT_FOUND, message='Not found', **kwargs) def patched_urlopen_500(self, method, url, **kwargs): return patched_urlopen_error( - method, url, code=httplib.INTERNAL_SERVER_ERROR, + method, url, code=http_client.INTERNAL_SERVER_ERROR, message='Internal server error', **kwargs) @@ -193,8 +196,8 @@ def test_client_read(): secret_key = 'secret' client = Client(public_key, secret_key, - oauth_access_token='some access token', - oauth_access_token_secret='some access token secret') + oauth_access_token='some access token', + oauth_access_token_secret='some access token secret') test_url = 'http://test.url' # Produce error on format other then json @@ -205,8 +208,8 @@ class NotJsonException(Exception): client.read(url=test_url, format='yaml') raise NotJsonException("Client.read() doesn't produce error on " "yaml format") - except NotJsonException, e: - raise e + except NotJsonException: + raise except Exception: pass @@ -222,51 +225,52 @@ class NotJsonException(Exception): "incorrect json response: {0}".format(result)) except IncorrectJsonResponseError: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 200 code " \ "and incorrect json response: " + str(e) # Test get, 400 error try: result = client_read_400(client=client, url=test_url) - except HTTP400BadRequestError, e: + except HTTP400BadRequestError: pass - except Exception, e: + except Exception as e: + raise assert 0, "Incorrect exception raised for 400 code: " + str(e) # Test get, 401 error try: result = client_read_401(client=client, url=test_url) - except HTTP401UnauthorizedError, e: + except HTTP401UnauthorizedError: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 401 code: " + str(e) # Test get, 403 error try: result = client_read_403(client=client, url=test_url) - except HTTP403ForbiddenError, e: + except HTTP403ForbiddenError: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 403 code: " + str(e) # Test get, 404 error try: result = client_read_404(client=client, url=test_url) - except HTTP404NotFoundError, e: + except HTTP404NotFoundError: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 404 code: " + str(e) # Test get, 500 error try: result = client_read_500(client=client, url=test_url) - except urllib2.HTTPError, e: - if e.code == httplib.INTERNAL_SERVER_ERROR: + except urllib.error.HTTPError as e: + if e.code == http_client.INTERNAL_SERVER_ERROR: pass else: assert 0, "Incorrect exception raised for 500 code: " + str(e) - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 500 code: " + str(e) @@ -322,18 +326,18 @@ def test_namespace(): teamrooms_dict = {'teamrooms': {'teamroom': - {u'team_ref': u'1', - u'name': u'oDesk', - u'recno': u'1', - u'parent_team_ref': u'1', - u'company_name': u'oDesk', - u'company_recno': u'1', - u'teamroom_api': u'/api/team/v1/teamrooms/odesk:some.json', - u'id': u'odesk:some'}}, + {'team_ref': '1', + 'name': 'oDesk', + 'recno': '1', + 'parent_team_ref': '1', + 'company_name': 'oDesk', + 'company_recno': '1', + 'teamroom_api': '/api/team/v1/teamrooms/odesk:some.json', + 'id': 'odesk:some'}}, 'teamroom': {'snapshot': 'test snapshot'}, 'snapshots': {'user': 'test', 'snapshot': 'test'}, 'snapshot': {'status': 'private'} - } + } def patched_urlopen_teamrooms(*args, **kwargs): @@ -403,141 +407,141 @@ def test_teamrooms_none(): eq_(te.get_snapshot(1, 1), teamrooms_dict_none['snapshot']) -userroles = {u'userrole': - [{u'parent_team__reference': u'1', - u'user__id': u'testuser', u'team__id': u'test:t', - u'reference': u'1', u'team__name': u'te', - u'company__reference': u'1', - u'user__reference': u'1', - u'user__first_name': u'Test', - u'user__last_name': u'Development', - u'parent_team__id': u'testdev', - u'team__reference': u'1', u'role': u'manager', - u'affiliation_status': u'none', u'engagement__reference': u'', - u'parent_team__name': u'TestDev', u'has_team_room_access': u'1', - u'company__name': u'Test Dev', - u'permissions': - {u'permission': [u'manage_employment', u'manage_recruiting']}}]} - -engagement = {u'status': u'active', - u'buyer_team__reference': u'1', u'provider__reference': u'2', - u'job__title': u'development', u'roles': {u'role': u'buyer'}, - u'reference': u'1', u'engagement_end_date': u'', - u'fixed_price_upfront_payment': u'0', - u'fixed_pay_amount_agreed': u'1.00', - u'provider__id': u'test_provider', - u'buyer_team__id': u'testteam:aa', - u'engagement_job_type': u'fixed-price', - u'job__reference': u'1', u'provider_team__reference': u'', - u'engagement_title': u'Developer', - u'fixed_charge_amount_agreed': u'0.01', - u'created_time': u'0000', u'provider_team__id': u'', - u'offer__reference': u'', - u'engagement_start_date': u'000', u'description': u''} - -engagements = {u'lister': - {u'total_items': u'10', u'query': u'', - u'paging': {u'count': u'10', u'offset': u'0'}, u'sort': u''}, - u'engagement': [engagement, engagement], +userroles = {'userrole': + [{'parent_team__reference': '1', + 'user__id': 'testuser', 'team__id': 'test:t', + 'reference': '1', 'team__name': 'te', + 'company__reference': '1', + 'user__reference': '1', + 'user__first_name': 'Test', + 'user__last_name': 'Development', + 'parent_team__id': 'testdev', + 'team__reference': '1', 'role': 'manager', + 'affiliation_status': 'none', 'engagement__reference': '', + 'parent_team__name': 'TestDev', 'has_team_room_access': '1', + 'company__name': 'Test Dev', + 'permissions': + {'permission': ['manage_employment', 'manage_recruiting']}}]} + +engagement = {'status': 'active', + 'buyer_team__reference': '1', 'provider__reference': '2', + 'job__title': 'development', 'roles': {'role': 'buyer'}, + 'reference': '1', 'engagement_end_date': '', + 'fixed_price_upfront_payment': '0', + 'fixed_pay_amount_agreed': '1.00', + 'provider__id': 'test_provider', + 'buyer_team__id': 'testteam:aa', + 'engagement_job_type': 'fixed-price', + 'job__reference': '1', 'provider_team__reference': '', + 'engagement_title': 'Developer', + 'fixed_charge_amount_agreed': '0.01', + 'created_time': '0000', 'provider_team__id': '', + 'offer__reference': '', + 'engagement_start_date': '000', 'description': ''} + +engagements = {'lister': + {'total_items': '10', 'query': '', + 'paging': {'count': '10', 'offset': '0'}, 'sort': ''}, + 'engagement': [engagement, engagement], } -offer = {u'provider__reference': u'1', - u'signed_by_buyer_user': u'', - u'reference': u'1', u'job__description': u'python', - u'buyer_company__name': u'Python community', - u'engagement_title': u'developer', u'created_time': u'000', - u'buyer_company__reference': u'2', u'buyer_team__id': u'testteam:aa', - u'interview_status': u'in_process', u'buyer_team__reference': u'1', - u'signed_time_buyer': u'', u'has_buyer_signed': u'', - u'signed_time_provider': u'', u'created_by': u'testuser', - u'job__reference': u'2', u'engagement_start_date': u'00000', - u'fixed_charge_amount_agreed': u'0.01', u'provider_team__id': u'', - u'status': u'', u'signed_by_provider_user': u'', - u'engagement_job_type': u'fixed-price', u'description': u'', - u'provider_team__name': u'', u'fixed_pay_amount_agreed': u'0.01', - u'candidacy_status': u'active', u'has_provider_signed': u'', - u'message_from_provider': u'', u'my_role': u'buyer', - u'key': u'~~0001', u'message_from_buyer': u'', - u'buyer_team__name': u'Python community 2', - u'engagement_end_date': u'', u'fixed_price_upfront_payment': u'0', - u'created_type': u'buyer', u'provider_team__reference': u'', - u'job__title': u'translation', u'expiration_date': u'', - u'engagement__reference': u''} - -offers = {u'lister': - {u'total_items': u'10', u'query': u'', u'paging': - {u'count': u'10', u'offset': u'0'}, u'sort': u''}, - u'offer': [offer, offer]} - -job = {u'subcategory': u'Development', u'reference': u'1', - u'buyer_company__name': u'Python community', - u'job_type': u'fixed-price', u'created_time': u'000', - u'created_by': u'test', u'duration': u'', - u'last_candidacy_access_time': u'', - u'category': u'Web', - u'buyer_team__reference': u'169108', u'title': u'translation', - u'buyer_company__reference': u'1', u'num_active_candidates': u'0', - u'buyer_team__name': u'Python community 2', u'start_date': u'000', - u'status': u'filled', u'num_new_candidates': u'0', - u'description': u'test', u'end_date': u'000', - u'public_url': u'http://www.odesk.com/jobs/~~0001', - u'visibility': u'invite-only', u'buyer_team__id': u'testteam:aa', - u'num_candidates': u'1', u'budget': u'1000', u'cancelled_date': u'', - u'filled_date': u'0000'} +offer = {'provider__reference': '1', + 'signed_by_buyer_user': '', + 'reference': '1', 'job__description': 'python', + 'buyer_company__name': 'Python community', + 'engagement_title': 'developer', 'created_time': '000', + 'buyer_company__reference': '2', 'buyer_team__id': 'testteam:aa', + 'interview_status': 'in_process', 'buyer_team__reference': '1', + 'signed_time_buyer': '', 'has_buyer_signed': '', + 'signed_time_provider': '', 'created_by': 'testuser', + 'job__reference': '2', 'engagement_start_date': '00000', + 'fixed_charge_amount_agreed': '0.01', 'provider_team__id': '', + 'status': '', 'signed_by_provider_user': '', + 'engagement_job_type': 'fixed-price', 'description': '', + 'provider_team__name': '', 'fixed_pay_amount_agreed': '0.01', + 'candidacy_status': 'active', 'has_provider_signed': '', + 'message_from_provider': '', 'my_role': 'buyer', + 'key': '~~0001', 'message_from_buyer': '', + 'buyer_team__name': 'Python community 2', + 'engagement_end_date': '', 'fixed_price_upfront_payment': '0', + 'created_type': 'buyer', 'provider_team__reference': '', + 'job__title': 'translation', 'expiration_date': '', + 'engagement__reference': ''} + +offers = {'lister': + {'total_items': '10', 'query': '', 'paging': + {'count': '10', 'offset': '0'}, 'sort': ''}, + 'offer': [offer, offer]} + +job = {'subcategory': 'Development', 'reference': '1', + 'buyer_company__name': 'Python community', + 'job_type': 'fixed-price', 'created_time': '000', + 'created_by': 'test', 'duration': '', + 'last_candidacy_access_time': '', + 'category': 'Web', + 'buyer_team__reference': '169108', 'title': 'translation', + 'buyer_company__reference': '1', 'num_active_candidates': '0', + 'buyer_team__name': 'Python community 2', 'start_date': '000', + 'status': 'filled', 'num_new_candidates': '0', + 'description': 'test', 'end_date': '000', + 'public_url': 'http://www.odesk.com/jobs/~~0001', + 'visibility': 'invite-only', 'buyer_team__id': 'testteam:aa', + 'num_candidates': '1', 'budget': '1000', 'cancelled_date': '', + 'filled_date': '0000'} jobs = [job, job] -task = {u'reference': u'test', u'company_reference': u'1', - u'team__reference': u'1', u'user__reference': u'1', - u'code': u'1', u'description': u'test task', - u'url': u'http://url.odesk.com/task', u'level': u'1'} +task = {'reference': 'test', 'company_reference': '1', + 'team__reference': '1', 'user__reference': '1', + 'code': '1', 'description': 'test task', + 'url': 'http://url.odesk.com/task', 'level': '1'} tasks = [task, task] -auth_user = {u'first_name': u'TestF', u'last_name': u'TestL', - u'uid': u'testuser', u'timezone_offset': u'0', - u'timezone': u'Europe/Athens', u'mail': u'test_user@odesk.com', - u'messenger_id': u'', u'messenger_type': u'yahoo'} - -user = {u'status': u'active', u'first_name': u'TestF', - u'last_name': u'TestL', u'reference': u'0001', - u'timezone_offset': u'10800', - u'public_url': u'http://www.odesk.com/users/~~000', - u'is_provider': u'1', - u'timezone': u'GMT+02:00 Athens, Helsinki, Istanbul', - u'id': u'testuser'} - -team = {u'status': u'active', u'parent_team__reference': u'0', - u'name': u'Test', - u'reference': u'1', - u'company__reference': u'1', - u'id': u'test', - u'parent_team__id': u'test_parent', - u'company_name': u'Test', u'is_hidden': u'', - u'parent_team__name': u'Test parent'} - -company = {u'status': u'active', - u'name': u'Test', - u'reference': u'1', - u'company_id': u'1', - u'owner_user_id': u'1', } - -hr_dict = {u'auth_user': auth_user, - u'server_time': u'0000', - u'user': user, - u'team': team, - u'company': company, - u'teams': [team, team], - u'companies': [company, company], - u'users': [user, user], - u'tasks': task, - u'userroles': userroles, - u'engagements': engagements, - u'engagement': engagement, - u'offer': offer, - u'offers': offers, - u'job': job, - u'jobs': jobs} +auth_user = {'first_name': 'TestF', 'last_name': 'TestL', + 'uid': 'testuser', 'timezone_offset': '0', + 'timezone': 'Europe/Athens', 'mail': 'test_user@odesk.com', + 'messenger_id': '', 'messenger_type': 'yahoo'} + +user = {'status': 'active', 'first_name': 'TestF', + 'last_name': 'TestL', 'reference': '0001', + 'timezone_offset': '10800', + 'public_url': 'http://www.odesk.com/users/~~000', + 'is_provider': '1', + 'timezone': 'GMT+02:00 Athens, Helsinki, Istanbul', + 'id': 'testuser'} + +team = {'status': 'active', 'parent_team__reference': '0', + 'name': 'Test', + 'reference': '1', + 'company__reference': '1', + 'id': 'test', + 'parent_team__id': 'test_parent', + 'company_name': 'Test', 'is_hidden': '', + 'parent_team__name': 'Test parent'} + +company = {'status': 'active', + 'name': 'Test', + 'reference': '1', + 'company_id': '1', + 'owner_user_id': '1', } + +hr_dict = {'auth_user': auth_user, + 'server_time': '0000', + 'user': user, + 'team': team, + 'company': company, + 'teams': [team, team], + 'companies': [company, company], + 'users': [user, user], + 'tasks': task, + 'userroles': userroles, + 'engagements': engagements, + 'engagement': engagement, + 'offer': offer, + 'offers': offers, + 'job': job, + 'jobs': jobs} def patched_urlopen_hr(*args, **kwargs): @@ -549,17 +553,17 @@ def test_get_hrv2_user(): hr = get_client().hr #test get_user - assert hr.get_user(1) == hr_dict[u'user'], hr.get_user(1) + assert hr.get_user(1) == hr_dict['user'], hr.get_user(1) @patch('urllib3.PoolManager.urlopen', patched_urlopen_hr) def test_get_hrv2_companies(): hr = get_client().hr #test get_companies - assert hr.get_companies() == hr_dict[u'companies'], hr.get_companies() + assert hr.get_companies() == hr_dict['companies'], hr.get_companies() #test get_company - assert hr.get_company(1) == hr_dict[u'company'], hr.get_company(1) + assert hr.get_company(1) == hr_dict['company'], hr.get_company(1) @patch('urllib3.PoolManager.urlopen', patched_urlopen_hr) @@ -582,18 +586,18 @@ def test_get_hrv2_company_users(): def test_get_hrv2_teams(): hr = get_client().hr #test get_teams - assert hr.get_teams() == hr_dict[u'teams'], hr.get_teams() + assert hr.get_teams() == hr_dict['teams'], hr.get_teams() #test get_team - assert hr.get_team(1) == hr_dict[u'team'], hr.get_team(1) + assert hr.get_team(1) == hr_dict['team'], hr.get_team(1) @patch('urllib3.PoolManager.urlopen', patched_urlopen_hr) def test_get_hrv2_team_users(): hr = get_client().hr #test get_team_users - assert hr.get_team_users(1) == hr_dict[u'users'], hr.get_team_users(1) - assert hr.get_team_users(1, False) == hr_dict[u'users'], \ + assert hr.get_team_users(1) == hr_dict['users'], hr.get_team_users(1) + assert hr.get_team_users(1, False) == hr_dict['users'], \ hr.get_team_users(1, False) @@ -608,8 +612,8 @@ def test_get_hrv2_userroles(): def test_get_hrv2_jobs(): hr = get_client().hr #test get_jobs - assert hr.get_jobs(1) == hr_dict[u'jobs'], hr.get_jobs() - assert hr.get_job(1) == hr_dict[u'job'], hr.get_job(1) + assert hr.get_jobs(1) == hr_dict['jobs'], hr.get_jobs() + assert hr.get_job(1) == hr_dict['job'], hr.get_job(1) result = hr.update_job(1, 2, 'title', 'desc', 'public', budget=100, status='open') eq_(result, hr_dict) @@ -620,22 +624,22 @@ def test_get_hrv2_jobs(): def test_get_hrv2_offers(): hr = get_client().hr #test get_offers - assert hr.get_offers(1) == hr_dict[u'offers'], hr.get_offers() - assert hr.get_offer(1) == hr_dict[u'offer'], hr.get_offer(1) + assert hr.get_offers(1) == hr_dict['offers'], hr.get_offers() + assert hr.get_offer(1) == hr_dict['offer'], hr.get_offer(1) @patch('urllib3.PoolManager.urlopen', patched_urlopen_hr) def test_get_hrv2_engagements(): hr = get_client().hr - eq_(hr.get_engagements(), hr_dict[u'engagements']) + eq_(hr.get_engagements(), hr_dict['engagements']) - eq_(hr.get_engagements(provider_reference=1), hr_dict[u'engagements']) - eq_(hr.get_engagements(profile_key=1), hr_dict[u'engagements']) - eq_(hr.get_engagement(1), hr_dict[u'engagement']) + eq_(hr.get_engagements(provider_reference=1), hr_dict['engagements']) + eq_(hr.get_engagements(profile_key=1), hr_dict['engagements']) + eq_(hr.get_engagement(1), hr_dict['engagement']) -adjustments = {u'adjustment': {u'reference': '100'}} +adjustments = {'adjustment': {'reference': '100'}} def patched_urlopen_hradjustment(*args, **kwargs): @@ -649,12 +653,12 @@ def test_hrv2_post_adjustment(): # Using ``amount`` result = hr.post_team_adjustment( 1, 2, 'a test', amount=100, notes='test note') - assert result == adjustments[u'adjustment'], result + assert result == adjustments['adjustment'], result # Using ``charge_amount`` result = hr.post_team_adjustment( 1, 2, 'a test', charge_amount=100, notes='test note') - assert result == adjustments[u'adjustment'], result + assert result == adjustments['adjustment'], result try: # Using ``amount`` and ``charge_amount`` will raise error @@ -691,7 +695,7 @@ def test_hrv2_post_adjustment(): def patched_urlopen_job_data_parameters(self, method, url, **kwargs): - post_dict = urlparse.parse_qs(kwargs.get('body')) + post_dict = urllib.parse.parse_qs(kwargs.get('body')) post_dict.pop('oauth_timestamp') post_dict.pop('oauth_signature') post_dict.pop('oauth_nonce') @@ -719,27 +723,30 @@ def test_job_data_parameters(): provider_dict = {'profile': - {u'response_time': u'31.0000000000000000', - u'dev_agency_ref': u'', - u'dev_adj_score_recent': u'0', - u'dev_ui_profile_access': u'Public', - u'dev_portrait': u'', - u'dev_ic': u'Freelance Provider', - u'certification': u'', - u'dev_usr_score': u'0', - u'dev_country': u'Ukraine', - u'dev_recent_rank_percentile': u'0', - u'dev_profile_title': u'Python developer', - u'dev_groups': u'', - u'dev_scores': - {u'dev_score': - [{u'description': u'competency and skills for the job, understanding of specifications/instructions', - u'avg_category_score_recent': u'', - u'avg_category_score': u'', - u'order': u'1', u'label': u'Skills'}, - {u'description': u'quality of work deliverables', - u'avg_category_score_recent': u'', - u'avg_category_score': u'', u'order': u'2', u'label': u'Quality'}, + {'response_time': '31.0000000000000000', + 'dev_agency_ref': '', + 'dev_adj_score_recent': '0', + 'dev_ui_profile_access': 'Public', + 'dev_portrait': '', + 'dev_ic': 'Freelance Provider', + 'certification': '', + 'dev_usr_score': '0', + 'dev_country': 'Ukraine', + 'dev_recent_rank_percentile': '0', + 'dev_profile_title': 'Python developer', + 'dev_groups': '', + 'dev_scores': + {'dev_score': [ + {'description': + 'competency and skills for the job, understanding of ' + 'specifications/instructions', + 'avg_category_score_recent': '', + 'avg_category_score': '', + 'order': '1', 'label': 'Skills'}, + {'description': 'quality of work deliverables', + 'avg_category_score_recent': '', + 'avg_category_score': '', 'order': '2', + 'label': 'Quality'}, ] }}, 'providers': {'test': 'test'}, @@ -754,8 +761,7 @@ def test_job_data_parameters(): 'quick_info': 'quick_info', 'categories': 'category 1', 'regions': 'region 1', - 'tests': 'test 1', - } + 'tests': 'test 1'} def patched_urlopen_provider(*args, **kwargs): @@ -798,18 +804,18 @@ def test_provider(): assert result == provider_dict['tests'] -trays_dict = {'trays': [{u'unread': u'0', - u'type': u'sent', - u'id': u'1', - u'tray_api': u'/api/mc/v1/trays/username/sent.json'}, - {u'unread': u'0', - u'type': u'inbox', - u'id': u'2', - u'tray_api': u'/api/mc/v1/trays/username/inbox.json'}, - {u'unread': u'0', - u'type': u'notifications', - u'id': u'3', - u'tray_api': u'/api/mc/v1/trays/username/notifications.json'}]} +trays_dict = {'trays': [{'unread': '0', + 'type': 'sent', + 'id': '1', + 'tray_api': '/api/mc/v1/trays/username/sent.json'}, + {'unread': '0', + 'type': 'inbox', + 'id': '2', + 'tray_api': '/api/mc/v1/trays/username/inbox.json'}, + {'unread': '0', + 'type': 'notifications', + 'id': '3', + 'tray_api': '/api/mc/v1/trays/username/notifications.json'}]} def patched_urlopen_trays(*args, **kwargs): @@ -827,7 +833,7 @@ def test_get_trays(): #test get_trays assert mc.get_trays(1) == trays_dict['trays'], mc.get_trays(1) assert mc.get_trays(1, paging_offset=10, paging_count=10) ==\ - trays_dict['trays'], mc.get_trays(1, paging_offset=10, paging_count=10) + trays_dict['trays'], mc.get_trays(1, paging_offset=10, paging_count=10) tray_content_dict = {"current_tray": {"threads": '1'}} @@ -843,10 +849,10 @@ def test_get_tray_content(): #test get_tray_content assert mc.get_tray_content(1, 1) ==\ - tray_content_dict['current_tray']['threads'], mc.get_tray_content(1, 1) + tray_content_dict['current_tray']['threads'], mc.get_tray_content(1, 1) assert mc.get_tray_content(1, 1, paging_offset=10, paging_count=10) ==\ - tray_content_dict['current_tray']['threads'], \ - mc.get_tray_content(1, 1, paging_offset=10, paging_count=10) + tray_content_dict['current_tray']['threads'], \ + mc.get_tray_content(1, 1, paging_offset=10, paging_count=10) thread_content_dict = {"thread": {"test": '1'}} @@ -934,24 +940,24 @@ def test_post_message(): assert reply == read_thread_content_dict, reply -timereport_dict = {u'table': - {u'rows': - [{u'c': - [{u'v': u'20100513'}, - {u'v': u'company1:team1'}, - {u'v': u'1'}, - {u'v': u'1'}, - {u'v': u'0'}, - {u'v': u'1'}, - {u'v': u'Bug 1: Test'}]}], - u'cols': - [{u'type': u'date', u'label': u'worked_on'}, - {u'type': u'string', u'label': u'assignment_team_id'}, - {u'type': u'number', u'label': u'hours'}, - {u'type': u'number', u'label': u'earnings'}, - {u'type': u'number', u'label': u'earnings_offline'}, - {u'type': u'string', u'label': u'task'}, - {u'type': u'string', u'label': u'memo'}]}} +timereport_dict = {'table': + {'rows': + [{'c': + [{'v': '20100513'}, + {'v': 'company1:team1'}, + {'v': '1'}, + {'v': '1'}, + {'v': '0'}, + {'v': '1'}, + {'v': 'Bug 1: Test'}]}], + 'cols': + [{'type': 'date', 'label': 'worked_on'}, + {'type': 'string', 'label': 'assignment_team_id'}, + {'type': 'number', 'label': 'hours'}, + {'type': 'number', 'label': 'earnings'}, + {'type': 'number', 'label': 'earnings_offline'}, + {'type': 'string', 'label': 'task'}, + {'type': 'string', 'label': 'memo'}]}} def patched_urlopen_timereport_content(*args, **kwargs): @@ -999,24 +1005,24 @@ def test_get_agency_timereport(): hours=True) assert read == timereport_dict, read -fin_report_dict = {u'table': - {u'rows': - [{u'c': - [{u'v': u'20100513'}, - {u'v': u'odesk:odeskps'}, - {u'v': u'1'}, - {u'v': u'1'}, - {u'v': u'0'}, - {u'v': u'1'}, - {u'v': u'Bug 1: Test'}]}], - u'cols': - [{u'type': u'date', u'label': u'worked_on'}, - {u'type': u'string', u'label': u'assignment_team_id'}, - {u'type': u'number', u'label': u'hours'}, - {u'type': u'number', u'label': u'earnings'}, - {u'type': u'number', u'label': u'earnings_offline'}, - {u'type': u'string', u'label': u'task'}, - {u'type': u'string', u'label': u'memo'}]}} +fin_report_dict = {'table': + {'rows': + [{'c': + [{'v': '20100513'}, + {'v': 'odesk:odeskps'}, + {'v': '1'}, + {'v': '1'}, + {'v': '0'}, + {'v': '1'}, + {'v': 'Bug 1: Test'}]}], + 'cols': + [{'type': 'date', 'label': 'worked_on'}, + {'type': 'string', 'label': 'assignment_team_id'}, + {'type': 'number', 'label': 'hours'}, + {'type': 'number', 'label': 'earnings'}, + {'type': 'number', 'label': 'earnings_offline'}, + {'type': 'string', 'label': 'task'}, + {'type': 'string', 'label': 'memo'}]}} def patched_urlopen_fin_report_content(*args, **kwargs): @@ -1119,7 +1125,7 @@ def test_get_financial_entities_provider(): assert read == fin_report_dict, read -task_dict = {u'tasks': 'task1'} +task_dict = {'tasks': 'task1'} def patched_urlopen_task(*args, **kwargs): @@ -1288,9 +1294,11 @@ def test_oauth_get_request_token(): def test_oauth_get_authorize_url(): oa = setup_oauth() assert oa.get_authorize_url() ==\ - 'https://www.odesk.com/services/api/auth?oauth_token=709d434e6b37a25c50e95b0e57d24c46' + 'https://www.odesk.com/services/api/auth?oauth_token=709d434e6b37a25c50e95b0e57d24c46',\ + oa.get_authorize_url() assert oa.get_authorize_url('http://example.com/oauth/complete') ==\ - 'https://www.odesk.com/services/api/auth?oauth_token=709d434e6b37a25c50e95b0e57d24c46&oauth_callback=http%3A%2F%2Fexample.com%2Foauth%2Fcomplete' + 'https://www.odesk.com/services/api/auth?oauth_token=709d434e6b37a25c50e95b0e57d24c46&oauth_callback=http%3A%2F%2Fexample.com%2Foauth%2Fcomplete',\ + oa.get_authorize_url('http://example.com/oauth/complete') def patched_httplib2_access(*args, **kwargs): return {'status': '200'},\ @@ -1308,79 +1316,79 @@ def test_oauth_get_access_token(): job_profiles_dict = {'profiles': {'profile': [ { - u'amount': u'', - u'as_hrs_per_week': u'0', - u'as_job_type': u'Hourly', - u'as_opening_access': u'private', - u'as_opening_recno': u'111', - u'as_opening_title': u'Review website and improve copy writing', - u'as_provider': u'111', - u'as_rate': u'$10.00', - u'as_reason': u'Job was cancelled or postponed', - u'as_reason_api_ref': u'', - u'as_reason_recno': u'72', - u'as_recno': u'1', - u'as_status': u'Closed', - u'as_to': u'11/2011', - u'as_total_charge': u'84', - u'as_total_hours': u'3.00', - u'op_desc_digest': u'Test job 1.', - u'op_description': u'Test job 1.', - u'ciphertext': u'~~111111111', - u'ui_job_profile_access': u'odesk', - u'ui_opening_status': u'Active', - u'version': u'1' + 'amount': '', + 'as_hrs_per_week': '0', + 'as_job_type': 'Hourly', + 'as_opening_access': 'private', + 'as_opening_recno': '111', + 'as_opening_title': 'Review website and improve copy writing', + 'as_provider': '111', + 'as_rate': '$10.00', + 'as_reason': 'Job was cancelled or postponed', + 'as_reason_api_ref': '', + 'as_reason_recno': '72', + 'as_recno': '1', + 'as_status': 'Closed', + 'as_to': '11/2011', + 'as_total_charge': '84', + 'as_total_hours': '3.00', + 'op_desc_digest': 'Test job 1.', + 'op_description': 'Test job 1.', + 'ciphertext': '~~111111111', + 'ui_job_profile_access': 'odesk', + 'ui_opening_status': 'Active', + 'version': '1' }, { - u'amount': u'', - u'as_hrs_per_week': u'0', - u'as_job_type': u'Hourly', - u'as_opening_access': u'private', - u'as_opening_recno': u'222', - u'as_opening_title': u'Review website and improve copy writing', - u'as_provider': u'222', - u'as_rate': u'$10.00', - u'as_reason': u'Job was cancelled or postponed', - u'as_reason_api_ref': u'', - u'as_reason_recno': u'72', - u'as_recno': u'2', - u'as_status': u'Closed', - u'as_to': u'11/2011', - u'as_total_charge': u'84', - u'as_total_hours': u'3.00', - u'ciphertext': u'~~222222222', - u'op_desc_digest': u'Test job 2.', - u'op_description': u'Test job 2.', - u'ui_job_profile_access': u'odesk', - u'ui_opening_status': u'Active', - u'version': u'1' + 'amount': '', + 'as_hrs_per_week': '0', + 'as_job_type': 'Hourly', + 'as_opening_access': 'private', + 'as_opening_recno': '222', + 'as_opening_title': 'Review website and improve copy writing', + 'as_provider': '222', + 'as_rate': '$10.00', + 'as_reason': 'Job was cancelled or postponed', + 'as_reason_api_ref': '', + 'as_reason_recno': '72', + 'as_recno': '2', + 'as_status': 'Closed', + 'as_to': '11/2011', + 'as_total_charge': '84', + 'as_total_hours': '3.00', + 'ciphertext': '~~222222222', + 'op_desc_digest': 'Test job 2.', + 'op_description': 'Test job 2.', + 'ui_job_profile_access': 'odesk', + 'ui_opening_status': 'Active', + 'version': '1' }, ]}} job_profile_dict = {'profile': { - u'amount': u'', - u'as_hrs_per_week': u'0', - u'as_job_type': u'Hourly', - u'as_opening_access': u'private', - u'as_opening_recno': u'111', - u'as_opening_title': u'Review website and improve copy writing', - u'as_provider': u'111', - u'as_rate': u'$10.00', - u'as_reason': u'Job was cancelled or postponed', - u'as_reason_api_ref': u'', - u'as_reason_recno': u'72', - u'as_recno': u'1', - u'as_status': u'Closed', - u'as_to': u'11/2011', - u'as_total_charge': u'84', - u'as_total_hours': u'3.00', - u'op_desc_digest': u'Test job 1.', - u'op_description': u'Test job 1.', - u'ciphertext': u'~~111111111', - u'ui_job_profile_access': u'odesk', - u'ui_opening_status': u'Active', - u'version': u'1' + 'amount': '', + 'as_hrs_per_week': '0', + 'as_job_type': 'Hourly', + 'as_opening_access': 'private', + 'as_opening_recno': '111', + 'as_opening_title': 'Review website and improve copy writing', + 'as_provider': '111', + 'as_rate': '$10.00', + 'as_reason': 'Job was cancelled or postponed', + 'as_reason_api_ref': '', + 'as_reason_recno': '72', + 'as_recno': '1', + 'as_status': 'Closed', + 'as_to': '11/2011', + 'as_total_charge': '84', + 'as_total_hours': '3.00', + 'op_desc_digest': 'Test job 1.', + 'op_description': 'Test job 1.', + 'ciphertext': '~~111111111', + 'ui_job_profile_access': 'odesk', + 'ui_opening_status': 'Active', + 'version': '1' } } @@ -1406,17 +1414,17 @@ def test_single_job_profile(): try: job.get_job_profile({}) raise Exception('Request should raise ValueError exception.') - except ValueError, e: + except ValueError as e: assert 'Invalid job key' in str(e) try: job.get_job_profile(['~~{0}'.format(x) for x in range(21)]) raise Exception('Request should raise ValueError exception.') - except ValueError, e: + except ValueError as e: assert 'Number of keys per request is limited' in str(e) try: job.get_job_profile(['~~111111', 123456]) raise Exception('Request should raise ValueError exception.') - except ValueError, e: + except ValueError as e: assert 'List should contain only job keys not recno' in str(e) # Get single job profile test diff --git a/odesk/utils.py b/odesk/utils.py index 80af739..4e7adc4 100644 --- a/odesk/utils.py +++ b/odesk/utils.py @@ -156,8 +156,10 @@ def __getitem__(self, key): if not isinstance(key, (slice, int)): raise TypeError if isinstance(key, slice): + # TODO: not working in py3 return [dict(zip(self.cols, row)) for row in self.rows[key]] else: + # TODO: not working in py3 return dict(zip(self.cols, self.rows[key])) def __len__(self): diff --git a/setup.py b/setup.py index 4e85e74..a98707c 100644 --- a/setup.py +++ b/setup.py @@ -1,5 +1,7 @@ # Copyright (c) 2010-2014, oDesk http://www.odesk.com # All rights reserved. +from __future__ import print_function + import re import os from setuptools import setup, find_packages @@ -11,7 +13,7 @@ readme.close() -VERSION = (0, 5, 2, 'final', 0) +VERSION = (0, 6, 0, 'alpha', 0) def get_version(): @@ -32,7 +34,7 @@ def update_init(version): """Update version number in the ``odesk/__init__.py``. """ - print 'Updating ``odesk/__init__.py`` to version "{0}"'.format(version) + print('Updating ``odesk/__init__.py`` to version "{0}"'.format(version)) # Update 'VERSION' variable in ``odesk/__init__.py`` with open('odesk/__init__.py', 'r') as f: init_contents = f.read() @@ -49,7 +51,7 @@ def update_init(version): with open('odesk/__init__.py', 'w') as f: f.write(new_init) - print 'OK' + print('OK') class UpdateVersion(Command): @@ -66,6 +68,10 @@ def finalize_options(self): def run(self): update_init(get_version()) +# NOTE: as official oauth2 not supporting python3, +# branch https://github.com/tseaver/python-oauth2/tree/py3-redux used insted +# setuptools cannot install from githubbranch, so you need to install manually +# pip install -e git+https://github.com/tseaver/python-oauth2@py3-redux#egg=oauth setup(cmdclass={'update_version': UpdateVersion}, name='python-odesk', @@ -76,7 +82,7 @@ def run(self): author_email='python@odesk.com', maintainer='Kirill Panshin', maintainer_email='kamelok@odesk.com', - install_requires=['oauth2', 'urllib3'], + install_requires=['oauth2', 'urllib3', 'six'], packages=find_packages(), license='BSD', download_url='http://github.com/odesk/python-odesk',