diff --git a/README b/README index 2879a2b..f9eadf7 100644 --- a/README +++ b/README @@ -1,11 +1,10 @@ Copyright (c) 2010-2011, oDesk http://www.odesk.com All rights reserved. -Python bindings to oDesk API +Python3 bindings to oDesk API. Python3 port of python-odesk. -* Git repo: http://github.com/odesk/python-odesk +* Git repo: http://github.com/vihtinsky/python-odesk3 * Issues: http://github.com/odesk/python-odesk/issues * Documentation: http://odesk.github.com/python-odesk/ -* Mailing list: python-odesk@googlegroups.com -* Facebook group: http://www.facebook.com/group.php?gid=136364403050710 + diff --git a/README.md b/README.md index 66a0fe3..2f40b3e 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,10 @@ Copyright (c) 2010-2011, oDesk http://www.odesk.com All rights reserved. -Python bindings to oDesk API +Python3 bindings to oDesk API ======================================= -* [Git repo](http://github.com/odesk/python-odesk) +* [Git repo](http://github.com/vihtinsky/python-odesk3) * [Issues](http://github.com/odesk/python-odesk/issues) * [Documentation](http://odesk.github.com/python-odesk/) -* [Mailing list](http://groups.google.com/group/python-odesk) -* [Facebook group](http://www.facebook.com/group.php?gid=136364403050710) + diff --git a/changelog.rst b/changelog.rst deleted file mode 100644 index d2a9d5d..0000000 --- a/changelog.rst +++ /dev/null @@ -1,66 +0,0 @@ -.. _changelog: - - -*************** -Changelog -*************** - -.. - -.. _0.4: - -Version 0.4 ------------------ -*May 2011* - -* *Incompatibility with previous release* Changed name of the otask router to the task -* *Incompatibility with previous release* Chaged name of the oticket router to the ticket ?? -* *Incompatibility with previous release* Changed name of the time_report router to the timereport -* *Incompatibility with previous release* Changed name of the finreports router to the finreport -* *Incompatibility with previous release* "from odesk import *" now import only: "get_version", "Client", "utils" -* All routers moved from the __init__.py to the own files in the routers dir. -* All helper classes moved to own modules -* Added logging inside exceptions -* Added possiblity to switch off unused routers inside client class -* Added oconomy, finance routers -* Added oDesk oAuth support - -.. _0.2: - -Version 0.2 ------------------ -*October 2010* - -* All helpers classes moved to the utils.py, added Table helper class -* *Incompatibility with previous release* Changed names of the methods' params to reflect real oDesk params - e.g. company_reference vs company name - -.. _0.1.2: - -Version 0.1.2 ------------------ -*29 September 2010* - -Bug fix release - -* Fixed check_token method -* Fixed KeyError on empty workdiaries - -.. _0.1.1: - -Version 0.1.1 ------------------ -*15 July 2010* - -Bug fix release - -* Fixed HR2.get_user_role(user_id=None, team_id=None, sub_teams=False) method to correctly get user roles when both user reference and team reference were submitted - previously only one of them was used in the request -* Documentation fixes - -.. _0.1: - -Version 0.1 ------------------ -*08 July 2010* - -First public release - diff --git a/examples/examples.py b/examples/examples.py index a7ea770..5d5da0d 100644 --- a/examples/examples.py +++ b/examples/examples.py @@ -12,17 +12,17 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def web_based_app(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user + print("Authenticated user:") + print(user) #Instantiating a new client, now with a token. #Not strictly necessary here (could just set `client.auth_token`), but #typical for web apps, which wouldn't probably keep client instances @@ -30,36 +30,36 @@ def web_based_app(public_key, secret_key): client = odesk.Client(public_key, secret_key, auth_token) try: - print "Team rooms:" - print client.team.get_teamrooms() + print("Team rooms:") + print(client.team.get_teamrooms()) #HRv2 API - print "HR: companies" - print client.hr.get_companies() - print "HR: teams" - print client.hr.get_teams() - print "HR: offers" - print client.hr.get_offers() - print "HR: get_engagements" - print client.hr.get_engagements() - print "HR: userroles" - print client.hr.get_user_role() - print "HR: candidacy stats" - print client.hr.get_candidacy_stats() - print "Get jobs" - print client.provider.get_jobs({'q': 'python'}) - print "Financial: withdrawal methods" - print client.finance.get_withdrawal_methods() - print "Revoke access" - print client.auth.revoke_token() - except Exception, e: - print "Exception at %s %s" % (client.last_method, client.last_url) + print("HR: companies") + print(client.hr.get_companies()) + print("HR: teams") + print(client.hr.get_teams()) + print("HR: offers") + print(client.hr.get_offers()) + print("HR: get_engagements") + print(client.hr.get_engagements()) + print("HR: userroles") + print(client.hr.get_user_role()) + print("HR: candidacy stats") + print(client.hr.get_candidacy_stats()) + print("Get jobs") + print(client.provider.get_jobs({'q': 'python'})) + print("Financial: withdrawal methods") + print(client.finance.get_withdrawal_methods()) + print("Revoke access") + print(client.auth.revoke_token()) + except Exception as e: + print("Exception at %s %s" % (client.last_method, client.last_url)) raise e if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') web_based_app(public_key, secret_key) diff --git a/examples/examples_oauth.py b/examples/examples_oauth.py index 58435a5..ec9ec78 100644 --- a/examples/examples_oauth.py +++ b/examples/examples_oauth.py @@ -12,15 +12,19 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def web_based_app(public_key, secret_key): - print "Emulating web-based app" + print ("Emulating web-based app") #Instantiating a client without an auth token client = odesk.Client(public_key, secret_key, auth='oauth') - 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: ') + print ("Please to this URL (authorize the app if necessary):") + #import pdb + #pdb.set_trace() + print (client.auth.get_authorize_url()) + print ("After that you should be redirected back to your app URL with " + \ + "additional ?oauth_verifier= parameter") + verifier = input('Enter oauth_verifier: ') oauth_access_token, oauth_access_token_secret = client.auth.get_access_token(verifier) + #import pdb + #pdb.set_trace() #Instantiating a new client, now with a token. #Not strictly necessary here (could just set `client.oauth_access_token` #and `client.oauth_access_token_secret`), but typical for web apps, @@ -30,34 +34,34 @@ def web_based_app(public_key, secret_key): oauth_access_token_secret=oauth_access_token_secret) try: - print "Team rooms:" - print client.team.get_teamrooms() + print ("Team rooms:") + print (client.team.get_teamrooms()) #HRv2 API - print "HR: companies" - print client.hr.get_companies() - print "HR: teams" - print client.hr.get_teams() - print "HR: offers" - print client.hr.get_offers() - print "HR: get_engagements" - print client.hr.get_engagements() - print "HR: userroles" - print client.hr.get_user_role() - print "HR: candidacy stats" - print client.hr.get_candidacy_stats() - print "Get jobs" - print client.provider.get_jobs({'q': 'python'}) - print "Financial: withdrawal methods" - print client.finance.get_withdrawal_methods() - except Exception, e: - print "Exception at %s %s" % (client.last_method, client.last_url) + print ("HR: companies") + print (client.hr.get_companies()) + print ("HR: teams") + print (client.hr.get_teams()) + print ("HR: offers") + print (client.hr.get_offers()) + print ("HR: get_engagements") + print (client.hr.get_engagements()) + print ("HR: userroles") + print (client.hr.get_user_role()) + print ("HR: candidacy stats") + print (client.hr.get_candidacy_stats()) + print ("Get jobs") + print (client.provider.get_jobs({'q': 'python'})) + print ("Financial: withdrawal methods") + print (client.finance.get_withdrawal_methods()) + except Exception as e: + print ("Exception at %s %s" % (client.last_method, client.last_url)) raise e if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') web_based_app(public_key, secret_key) diff --git a/examples/fin_reports.py b/examples/fin_reports.py index 62aadd4..465320f 100644 --- a/examples/fin_reports.py +++ b/examples/fin_reports.py @@ -4,6 +4,7 @@ (C) 2010 oDesk """ import odesk +import odesk.utils from datetime import date @@ -14,31 +15,31 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def fin_reports(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user - #Instantiating a new client, now with a token. - #Not strictly necessary here (could just set `client.auth_token`), but - #typical for web apps, which wouldn't probably keep client instances + print("Authenticated user:") + print(user) + #Instantiating a new client, now with a token. + #Not strictly necessary here (could just set `client.auth_token`), but + #typical for web apps, which wouldn't probably keep client instances #between requests client = odesk.Client(public_key, secret_key, auth_token) - print client.finreports.get_provider_billings('1111', - odesk.Query(select=['date', 'type', - 'amount'], - where=((odesk.Q('date') <= date.today())))) + print(client.finreport.get_provider_billings('11111', + odesk.utils.Query(select=['date', 'type', + 'amount'], + where=((odesk.utils.Q('date') <= date.today()))))) + - if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') fin_reports(public_key, secret_key) diff --git a/examples/get_create_update_jobs.py b/examples/get_create_update_jobs.py index af6d157..bc5eb30 100644 --- a/examples/get_create_update_jobs.py +++ b/examples/get_create_update_jobs.py @@ -12,17 +12,17 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def hr_post_job(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user + print("Authenticated user:") + print(user) #Instantiating a new client, now with a token. #Not strictly necessary here (could just set `client.auth_token`), but #typical for web apps, which wouldn't probably keep client instances @@ -39,17 +39,17 @@ def hr_post_job(public_key, secret_key): 'subcategory': 'Other - Web Development', } try: - print client.hr.post_job(job_data) - except Exception, e: - print "Exception at %s %s" % (client.last_method, client.last_url) + print(client.hr.post_job(job_data)) + except Exception as e: + print("Exception at %s %s" % (client.last_method, client.last_url)) raise e if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') hr_post_job(public_key, secret_key) diff --git a/examples/oconomy.py b/examples/oconomy.py index f15a511..c27197d 100644 --- a/examples/oconomy.py +++ b/examples/oconomy.py @@ -12,54 +12,48 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def oconomy(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user - #Instantiating a new client, now with a token. - #Not strictly necessary here (could just set `client.auth_token`), but - #typical for web apps, which wouldn't probably keep client instances + print("Authenticated user:") + print(user) + #Instantiating a new client, now with a token. + #Not strictly necessary here (could just set `client.auth_token`), but + #typical for web apps, which wouldn't probably keep client instances #between requests client = odesk.Client(public_key, secret_key, auth_token) - print client.oconomy.get_summary(2010,12) - - print client.oconomy.get_hours_worked_by_locations() - print client.oconomy.get_hours_worked_by_weeks() - print client.oconomy.get_top_countries_by_hours() - print client.oconomy.get_charges_by_categories() - print client.oconomy.get_most_requested_skills() - - print client.gds_oconomy.get_summary(2010,12) - - print client.gds_oconomy.get_hours_worked_by_locations() - print client.gds_oconomy.get_hours_worked_by_weeks() - print client.gds_oconomy.get_top_countries_by_hours() - print client.gds_oconomy.get_charges_by_categories() - print client.gds_oconomy.get_most_requested_skills() + print(client.oconomy.get_summary(2010,12)) + + print(client.oconomy.get_hours_worked_by_locations()) + print(client.oconomy.get_hours_worked_by_weeks()) + print(client.oconomy.get_top_countries_by_hours()) + print(client.oconomy.get_charges_by_categories()) + print(client.oconomy.get_most_requested_skills()) + + print(client.nonauth_oconomy.get_hours_worked_by_locations()) + print(client.nonauth_oconomy.get_hours_worked_by_weeks()) + print("top countries by hours") + print(client.nonauth_oconomy.get_top_countries_by_hours()) + print(client.nonauth_oconomy.get_most_requested_skills()) + + print("monthly summary") + print(client.nonauth_oconomy.get_monthly_summary('201011')) + print("hours worked by locations") + print(client.nonauth_oconomy.get_hours_worked_by_locations()) + print("earnings by categories") + print(client.nonauth_oconomy.get_earnings_by_categories()) + print("most requested skills") + print(client.oconomy.get_most_requested_skills()) + - print "monthly summary" - print client.oconomy.get_monthly_summary('201011') - print "hours worked by locations" - print client.oconomy.get_hours_worked_by_locations() - print "hours worked by weeks" - print client.oconomy.get_hours_worked_by_weeks() - print "top countries by hours" - print client.oconomy.get_top_countries_by_hours() - print "earnings by categories" - print client.oconomy.get_earnings_by_categories() - print "most requested skills" - print client.oconomy.get_most_requested_skills() - - if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') oconomy(public_key, secret_key) diff --git a/examples/provider.py b/examples/provider.py index dfb3f4d..2e89694 100644 --- a/examples/provider.py +++ b/examples/provider.py @@ -9,50 +9,42 @@ PUBLIC_KEY = None SECRET_KEY = None + #TODO: Desktop app example (check if it's working at all - wasn't last time) def provider(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user - #Instantiating a new client, now with a token. - #Not strictly necessary here (could just set `client.auth_token`), but - #typical for web apps, which wouldn't probably keep client instances + print("Authenticated user:") + print(user) + #Instantiating a new client, now with a token. + #Not strictly necessary here (could just set `client.auth_token`), but + #typical for web apps, which wouldn't probably keep client instances #between requests client = odesk.Client(public_key, secret_key, auth_token) - # get skills - print "Provider skills:" - print client.provider.get_skills('~~someref') - # add new skill - print "Adding provider skill" - print client.provider.add_skill('~~someref', {'skill':'skill'}) - # update a skill by giving a skill_id and new data - print "Updating provider skill" - print client.provider.update_skill('~~someref', 123, {'skill':'skill'}) - # delete a skill by giving a skill_id - print "Deleting provider skill" - print client.provider.delete_skill('~~someref', 123) - # get quickinfo - print "Get quick info" - print client.provider.get_quickinfo('~~someref') - # update a quickinfo by giving new data - client.provider.update_quickinfo('~~someref', {'skill':'skill'}) - print client.provider.get_affiliates('someref') - print "Revoke access" - print client.auth.revoke_token() - - + print("Search providers:") + print(client.provider.get_providers({'q':'python'})) + print("Search jobs:") + print(client.provider.get_jobs({'q':'wowza'})) + print("Provider all:") + #someref is like 71de2d463c748623 + print(client.provider.get_provider('~~someref')) + print("Provider brief:") + print(client.provider.get_provider_brief('~~someref')) + print("Revoke access") + print(client.auth.revoke_token()) + + if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') provider(public_key, secret_key) diff --git a/examples/simple_messager.py b/examples/simple_messager.py index 7d49194..00a3af6 100644 --- a/examples/simple_messager.py +++ b/examples/simple_messager.py @@ -12,33 +12,33 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def simple_messager(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user - #Instantiating a new client, now with a token. - #Not strictly necessary here (could just set `client.auth_token`), but - #typical for web apps, which wouldn't probably keep client instances + print("Authenticated user:") + print(user) + #Instantiating a new client, now with a token. + #Not strictly necessary here (could just set `client.auth_token`), but + #typical for web apps, which wouldn't probably keep client instances #between requests client = odesk.Client(public_key, secret_key, auth_token) - print client.mc.get_trays() - #print client.mc.get_tray_content('username', 'inbox') - #print client.mc.get_thread_content('username', '00') - print client.mc.post_message('username', 'username2', 'test from api', 'test body') + print(client.mc.get_trays()) + #print(client.mc.get_tray_content('my_username', 'inbox')) + #print(client.mc.get_thread_content('my_username', '111111')) + print(client.mc.post_message('sender', 'recipient', 'test from api', 'test body')) if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') simple_messager(public_key, secret_key) diff --git a/examples/tasks.py b/examples/tasks.py new file mode 100644 index 0000000..b537ac8 --- /dev/null +++ b/examples/tasks.py @@ -0,0 +1,59 @@ +import odesk +#oAuth key +PUBLIC_KEY = None +SECRET_KEY = None + + +def web_based_app(public_key, secret_key): + print ("Emulating web-based app") + #Instantiating a client without an auth token + client = odesk.Client(public_key, secret_key, auth='oauth') + + 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 = input('Enter oauth_verifier: ') + + oauth_access_token, oauth_access_token_secret = client.auth.get_access_token(verifier) + + #Instantiating a new client, now with a token. + #Not strictly necessary here (could just set `client.oauth_access_token` + #and `client.oauth_access_token_secret`), but typical for web apps, + #which wouldn't probably keep client instances between requests + + client = odesk.Client(public_key, secret_key, auth='oauth', + oauth_access_token=oauth_access_token, + oauth_access_token_secret=oauth_access_token_secret) + + try: + print ("Tasks list:") + print (client.task.get_user_tasks('company_id', 'team_id', 'user_id')) + #Post new task + print(client.task.post_user_task(company_id='company', + team_id='team', user_id='provider', code='TEST_TASK', + description='Test api task', url='http://task_url.py' + )) + #Update task + print(client.task.post_user_task(company_id='company', + team_id='team', user_id='provider', code='TEST_TASK', + description='Test api updated', url='http://task_url.py' + )) + #Should be list of task_codes. If one task list of 1 element + print(client.task.delete_user_task(company_id='company', + team_id='team', user_id='provider', task_codes=["TEST_TASK", "TASK_2"] + )) + + except Exception as e: + print ("Exception at %s %s" % (client.last_method, client.last_url)) + raise e + + + +if __name__ == '__main__': + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') + + web_based_app(public_key, secret_key) + diff --git a/examples/time_reports.py b/examples/time_reports.py index 040195c..2e99b6c 100644 --- a/examples/time_reports.py +++ b/examples/time_reports.py @@ -4,6 +4,7 @@ (C) 2010 oDesk """ import odesk +import odesk.utils from datetime import date PUBLIC_KEY = None @@ -12,41 +13,41 @@ #TODO: Desktop app example (check if it's working at all - wasn't last time) def time_reports(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user - #Instantiating a new client, now with a token. - #Not strictly necessary here (could just set `client.auth_token`), but - #typical for web apps, which wouldn't probably keep client instances + print("Authenticated user:") + print(user) + #Instantiating a new client, now with a token. + #Not strictly necessary here (could just set `client.auth_token`), but + #typical for web apps, which wouldn't probably keep client instances #between requests client = odesk.Client(public_key, secret_key, auth_token) - print client.time_reports.get_provider_report('user1', - odesk.Query(select=odesk.Query.DEFAULT_TIMEREPORT_FIELDS, - where=(odesk.Q('worked_on') <= date.today()) &\ - (odesk.Q('worked_on') > '2010-05-01'))) - - print client.time_reports.get_provider_report('user1', - odesk.Query(select=odesk.Query.DEFAULT_TIMEREPORT_FIELDS, - where=(odesk.Q('worked_on') <= date.today()) &\ - (odesk.Q('worked_on') > '2010-05-01')), hours=True) - - print client.time_reports.get_agency_report('company1', 'agency1', - odesk.Query(select=odesk.Query.DEFAULT_TIMEREPORT_FIELDS, - where=(odesk.Q('worked_on') <= date.today()) &\ - (odesk.Q('worked_on') > '2010-05-01')), hours=True) - - + print(client.timereport.get_provider_report('user1', + odesk.utils.Query(select=odesk.utils.Query.DEFAULT_TIMEREPORT_FIELDS, + where=(odesk.utils.Q('worked_on') <= date.today()) &\ + (odesk.utils.Q('worked_on') > '2012-05-01')))) + + print(client.timereport.get_provider_report('user1', + odesk.utils.Query(select=odesk.utils.Query.DEFAULT_TIMEREPORT_FIELDS, + where=(odesk.utils.Q('worked_on') <= date.today()) &\ + (odesk.utils.Q('worked_on') > '2012-05-01')), hours=True)) + + print(client.timereport.get_agency_report('company1', 'agency1', + odesk.utils.Query(select=odesk.utils.Query.DEFAULT_TIMEREPORT_FIELDS, + where=(odesk.utils.Q('worked_on') <= date.today()) &\ + (odesk.utils.Q('worked_on') > '2010-05-01')), hours=True)) + + if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') time_reports(public_key, secret_key) diff --git a/examples/user_snapshot.py b/examples/user_snapshot.py index f03e7da..d8d4b52 100644 --- a/examples/user_snapshot.py +++ b/examples/user_snapshot.py @@ -9,34 +9,32 @@ PUBLIC_KEY = None SECRET_KEY = None -#TODO: Desktop app example (check if it's working at all - wasn't last time) def user_snapshots(public_key, secret_key): - print "Emulating web-based app" + print("Emulating web-based app") #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.auth_url() - print "After that you should be redirected back to your app URL with " + \ - "additional ?frob= parameter" - frob = raw_input('Enter frob: ') + print("Please to this URL (authorize the app if necessary):") + print(client.auth.auth_url()) + print("After that you should be redirected back to your app URL with " + \ + "additional ?frob= parameter") + frob = input('Enter frob: ') auth_token, user = client.auth.get_token(frob) - print "Authenticated user:" - print user + print("Authenticated user:") + print(user) #Instantiating a new client, now with a token. #Not strictly necessary here (could just set `client.auth_token`), but #typical for web apps, which wouldn't probably keep client instances #between requests client = odesk.Client(public_key, secret_key, auth_token) - print client.team.get_snapshot('company1', 'user1') - print client.team.update_snapshot('company1', 'user1', memo='Updated Memo') - print client.team.delete_snapshot('company1', 'user1', datetime=datetime.utcnow()) + print(client.team.get_snapshot('company1', 'user1')) + print(client.team.update_snapshot('company1', 'user1', memo='Updated Memo')) + print(client.team.delete_snapshot('company1', 'user1', datetime=datetime.utcnow())) - if __name__ == '__main__': - public_key = PUBLIC_KEY or raw_input('Enter public key: ') - secret_key = SECRET_KEY or raw_input('Enter secret key: ') + public_key = PUBLIC_KEY or input('Enter public key: ') + secret_key = SECRET_KEY or input('Enter secret key: ') user_snapshots(public_key, secret_key) diff --git a/fixers/__init__.py b/fixers/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fixers/fix_patch_in_tests.py b/fixers/fix_patch_in_tests.py new file mode 100644 index 0000000..9147681 --- /dev/null +++ b/fixers/fix_patch_in_tests.py @@ -0,0 +1,15 @@ +from lib2to3.fixer_base import BaseFix +from lib2to3.pgen2 import token + +class FixPatchInTests(BaseFix): + + _accept_type = token.STRING + + def match(self, node): + if node.value.strip("'\"") == 'urllib2.urlopen': + return True + return False + + def transform(self, node, results): + node.value = "'urllib.request.urlopen'" + node.changed() diff --git a/full_list.rst b/full_list.rst index 7a0c52a..25142f5 100644 --- a/full_list.rst +++ b/full_list.rst @@ -21,7 +21,6 @@ Package structure * routers * __init__.py - * finance.py * finreport.py * hr.py * mc.py @@ -29,9 +28,7 @@ Package structure * provider.py * task.py * team.py - * ticket.py * timereport.py - * url.py * tests.py @@ -191,8 +188,6 @@ oauth.py routers/ --------------------- -* Finances(Namespace) - routers/finance.py - * Finreports(GdsNamespace) - routers/finreport.py * get_provider_billings(self, provider_id, query) @@ -214,14 +209,11 @@ routers/ * get_companies(self) * get_company(self, company_id) * get_company_teams(self, company_id) - * get_company_tasks(self, company_id) - Not implemented in API * get_company_users(self, company_id, active=True) * get_teams(self) * get_team(self, team_id, include_users=False) - * get_team_tasks(self, team_id) - Not implemented in API * get_team_users(self, team_id, active=True) * post_team_adjustment(self, team_id, engagement_id, amount, comments, notes) - * get_tasks(self) - Not implemented in API * get_user_role(self, user_id=None, team_id=None, sub_teams=False) * get_jobs(self) * get_job(self, job_id) @@ -284,8 +276,6 @@ routers/ * get_snapshots(self, team_id, online='now') * get_workdiaries(self, team_id, username, date=None) -* Ticket(Namespace) - routers/ticket.py - * Timereport(GdsNamespace) - routers/timereport.py * get_provider_report(self, provider_id, query, hours=False) @@ -293,9 +283,6 @@ routers/ * get_agency_report(self, company_id, agency_id, query, hours=False) * query is the odesk.Query object -* Url(Namespace) - routers/url.py - - .. _utils: utils.py diff --git a/getting_started.rst b/getting_started.rst index 35562f2..ab40ab2 100644 --- a/getting_started.rst +++ b/getting_started.rst @@ -10,7 +10,10 @@ Getting started Requirements ----------------- -You need to install oauth2 to run the python-odesk, and mock and nosetests if you plan to develop python-odesk and/or run library's tests. +You need to install oauth2 to run the python-odesk3, and mock and nosetests if you plan to develop python-odesk and/or run library's tests. + +Oauth2(for python3):: + pip install -e https://github.com/hades/python-oauth2/tarball/python3#egg=oauth2 Mock:: @@ -34,17 +37,10 @@ To install:: python setup.py install -Or via easy_install:: - - easy_install python-odesk - -Or via pip:: - - pip install python-odesk Also, you can retrieve fresh version of python-odesk from GitHub:: - git clone git://github.com/odesk/python-odesk.git + git clone git://github.com/vihtinsky/python-odesk3.git .. _settings: diff --git a/how_to.rst b/how_to.rst index 46f584f..9965e2b 100644 --- a/how_to.rst +++ b/how_to.rst @@ -13,7 +13,7 @@ Authenticate http://developers.odesk.com/Authentication -To authenticate your web application with the python-odesk, use next code:: +To authenticate your web application with the python-odesk3, use next code:: client = odesk.Client('your public key', 'your secret key') #redirect your user to the client.auth.auth_url() diff --git a/index.rst b/index.rst index 20c1e80..e7ce07b 100644 --- a/index.rst +++ b/index.rst @@ -1,7 +1,7 @@ .. sampledoc documentation master file ****************************************** -Python bindings to oDesk API +Python3 bindings to oDesk API ****************************************** .. toctree:: @@ -19,8 +19,7 @@ Python bindings to oDesk API Urls ********************* -* Git repo: http://github.com/odesk/python-odesk +* Git repo: http://github.com/vihtinsky/python-odesk * Issues: http://github.com/odesk/python-odesk/issues * Documentation: http://odesk.github.com/python-odesk/ -* Mailing list: http://groups.google.com/group/python-odesk (python-odesk@googlegroups.com) -* Facebook group: http://www.facebook.com/group.php?gid=136364403050710 + diff --git a/odesk/__init__.py b/odesk/__init__.py index f7ecf55..6046e36 100644 --- a/odesk/__init__.py +++ b/odesk/__init__.py @@ -1,9 +1,9 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -VERSION = (0, 4, 0, 'final', 5) +VERSION = (0, 1, 0, 'beta', 1) def get_version(): @@ -20,39 +20,28 @@ def get_version(): return version -import cookielib -from datetime import date + import hashlib import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - +import urllib2, urllib +import json -from odesk.auth import * -from odesk.exceptions import * -from odesk.http import * -from odesk.namespaces import * -from odesk.utils import * +from odesk.auth import Auth +from odesk.oauth import OAuth +from odesk.http import HttpRequest, raise_http_error __all__ = ["get_version", "Client", "utils"] - def _utf8_str(obj): try: return unicode(obj).encode("utf8") except UnicodeDecodeError, e: # input could be an utf8 encoded + logging.debug(e) obj.decode("utf8") # check if it is a valid utf8 string return obj - def signed_urlencode(secret, query={}): """ Converts a mapping object to signed url query @@ -62,17 +51,16 @@ def signed_urlencode(secret, query={}): >>> signed_urlencode('some$ecret', {'spam':42,'foo':'bar'}) 'api_sig=11b1fc2e6555297bdc144aed0a5e641c&foo=bar&spam=42' """ - message = secret + message = _utf8_str(secret) for key in sorted(query.keys()): try: - message += _utf8_str(key) + _utf8_str(query[_utf8_str(key)]) - except Exception, e: + message += _utf8_str(key) + _utf8_str(query[key]) + except Exception as e: logging.debug("[python-odesk] Error while trying to sign key: %s and query %s" % (key, query[key])) raise e - #query = query.copy() _query = {} _query['api_sig'] = hashlib.md5(message).hexdigest() - for k, v in query.iteritems(): + for k, v in query.items(): _query[_utf8_str(k)] = _utf8_str(v) return urllib.urlencode(_query) @@ -97,7 +85,6 @@ def urlencode(self, data={}): return signed_urlencode(self.secret_key, data) def urlopen(self, url, data={}, method='GET'): - from odesk.oauth import OAuth data = data.copy() #FIXME: Http method hack. Should be removed once oDesk supports true @@ -111,8 +98,9 @@ def urlopen(self, url, data={}, method='GET'): self.last_data = data if isinstance(self.auth, OAuth): + http_method = 'GET' if method=='GET' else 'POST' query = self.auth.urlencode(url, self.oauth_access_token,\ - self.oauth_access_token_secret, data) + self.oauth_access_token_secret, data, http_method) else: query = self.urlencode(data) @@ -120,7 +108,7 @@ def urlopen(self, url, data={}, method='GET'): url += '?' + query request = HttpRequest(url=url, data=None, method=method) else: - request = HttpRequest(url=url, data=query, method=method) + request = HttpRequest(url=url, data=query.encode("utf-8"), method=method) return urllib2.urlopen(request) def read(self, url, data={}, method='GET', format='json'): @@ -131,11 +119,11 @@ def read(self, url, data={}, method='GET', format='json'): url += '.' + format try: response = self.urlopen(url, data, method) - except urllib2.HTTPError, e: + except urllib2.HTTPError as e: raise_http_error(e) if format == 'json': - result = json.loads(response.read()) + result = json.loads(response.read().decode("utf-8")) return result @@ -146,9 +134,9 @@ class Client(BaseClient): def __init__(self, public_key, secret_key, api_token=None, oauth_access_token=None, oauth_access_token_secret=None, - format='json', auth='simple', finance=True, finreport=True, + format='json', auth='simple', finreport=True, hr=True, mc=True, oconomy=True, provider=True, - task=True, team=True, ticket=True, timereport=True, url=True): + task=True, team=True, timereport=True): self.public_key = public_key self.secret_key = secret_key @@ -158,16 +146,11 @@ def __init__(self, public_key, secret_key, api_token=None, if auth == 'simple': self.auth = Auth(self) elif auth == 'oauth': - from odesk.oauth import OAuth self.auth = OAuth(self) self.oauth_access_token = oauth_access_token self.oauth_access_token_secret = oauth_access_token_secret #Namespaces - if finance: - from odesk.routers.finance import Finance - self.finance = Finance(self) - if finreport: from odesk.routers.finreport import Finreports self.finreport = Finreports(self) @@ -177,7 +160,7 @@ def __init__(self, public_key, secret_key, api_token=None, self.hr = HR(self) if mc: - from odesk.routers.mc import * + from odesk.routers.mc import MC self.mc = MC(self) if oconomy: @@ -197,17 +180,10 @@ def __init__(self, public_key, secret_key, api_token=None, from odesk.routers.team import Team self.team = Team(self) - if ticket: - from odesk.routers.ticket import Ticket - self.ticket = Ticket(self) - if timereport: from odesk.routers.timereport import TimeReport self.timereport = TimeReport(self) - if url: - from odesk.routers.url import Url - self.url = Url(self) #Shortcuts for HTTP methods def get(self, url, data={}): diff --git a/odesk/auth.py b/odesk/auth.py index f98ce3f..2482b64 100644 --- a/odesk/auth.py +++ b/odesk/auth.py @@ -1,23 +1,9 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - from odesk.namespaces import Namespace diff --git a/odesk/exceptions.py b/odesk/exceptions.py index ff8f472..6838e57 100644 --- a/odesk/exceptions.py +++ b/odesk/exceptions.py @@ -1,16 +1,16 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ import logging -import urllib2 +import urllib2, urllib class BaseException(Exception): def __init__(self, *args, **kwargs): - logging.debug("[python-odesk]:" + unicode(s) for s in args) + logging.debug("[python-odesk]:" + str(s) for s in args) super(BaseException, self).__init__() diff --git a/odesk/http.py b/odesk/http.py index bde90da..c1b9869 100644 --- a/odesk/http.py +++ b/odesk/http.py @@ -1,24 +1,13 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib import urllib2 - -try: - import json -except ImportError: - import simplejson as json - -from odesk.exceptions import * -from odesk.utils import * +from odesk.exceptions import (HTTP400BadRequestError, HTTP401UnauthorizedError, + HTTP403ForbiddenError, HTTP404NotFoundError) def raise_http_error(e): diff --git a/odesk/namespaces.py b/odesk/namespaces.py index 7cb4331..5de898e 100644 --- a/odesk/namespaces.py +++ b/odesk/namespaces.py @@ -1,25 +1,14 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib import urllib2 +import json +from odesk.http import raise_http_error, HttpRequest -try: - import json -except ImportError: - import simplejson as json - - -from odesk.http import * -from odesk.utils import * class Namespace(object): @@ -58,24 +47,41 @@ class GdsNamespace(Namespace): base_url = 'https://www.odesk.com/gds/' def urlopen(self, url, data={}, method='GET'): + from odesk.oauth import OAuth data = data.copy() - query = self.client.urlencode(data) + + #FIXME: Http method hack. Should be removed once oDesk supports true + #HTTP methods + if method in ['PUT', 'DELETE']: + data['http_method'] = method.lower() + #End of hack + + self.client.last_method = method + self.client.last_url = url + self.client.last_data = data + + if isinstance(self.client.auth, OAuth): + query = self.client.auth.urlencode(url, self.client.oauth_access_token,\ + self.client.oauth_access_token_secret, data) + else: + query = self.client.urlencode(data) if method == 'GET': url += '?' + query request = HttpRequest(url=url, data=None, method=method) return urllib2.urlopen(request) return None + def read(self, url, data={}, method='GET'): """ Returns parsed Python object or raises an error """ try: response = self.urlopen(url, data, method) - except urllib2.HTTPError, e: + except urllib2.HTTPError as e: raise_http_error(e) - result = json.loads(response.read()) + result = json.loads(response.read().decode("utf-8")) return result def get(self, url, data={}): @@ -90,7 +96,8 @@ class NonauthGdsNamespace(GdsNamespace): ''' def urlopen(self, url, data={}, method='GET'): if method == 'GET': - request = HttpRequest(url=url, data=data.copy(), - method=method) + query = self.client.urlencode(data) + url += '?' + query + request = HttpRequest(url=url, data=None, method=method) return urllib2.urlopen(request) return None diff --git a/odesk/oauth.py b/odesk/oauth.py index 0b6a64d..4da366a 100644 --- a/odesk/oauth.py +++ b/odesk/oauth.py @@ -1,20 +1,21 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ import time -import urlparse -import urllib +import urlparse, urllib import oauth2 as oauth from odesk.namespaces import Namespace -from odesk.http import HttpRequest class OAuth(Namespace): + """ + oAuth support in oDesk is in beta currently. + """ api_url = 'auth/' version = 1 @@ -52,12 +53,14 @@ def get_request_token(self): Returns request token and request token secret """ client = oauth.Client(self.get_oauth_consumer()) + #import pdb + #pdb.set_trace() response, content = client.request(self.request_token_url, 'POST') if response.get('status') != '200': raise Exception("Invalid request token response: %s." % content) request_token = dict(urlparse.parse_qsl(content)) - self.request_token = request_token.get('oauth_token') - self.request_token_secret = request_token.get('oauth_token_secret') + self.request_token = request_token.get(b'oauth_token') + self.request_token_secret = request_token.get(b'oauth_token_secret') return self.request_token, self.request_token_secret def get_authorize_url(self, callback_url=None): @@ -89,6 +92,6 @@ def get_access_token(self, verifier): if response.get('status') != '200': raise Exception("Invalid access token response: %s." % content) access_token = dict(urlparse.parse_qsl(content)) - self.access_token = access_token.get('oauth_token') - self.access_token_secret = access_token.get('oauth_token_secret') + self.access_token = access_token.get(b'oauth_token') + self.access_token_secret = access_token.get(b'oauth_token_secret') return self.access_token, self.access_token_secret diff --git a/odesk/routers/__init__.py b/odesk/routers/__init__.py index 3851dd2..d1e126f 100644 --- a/odesk/routers/__init__.py +++ b/odesk/routers/__init__.py @@ -1,5 +1,5 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ diff --git a/odesk/routers/finance.py b/odesk/routers/finance.py deleted file mode 100644 index 8121230..0000000 --- a/odesk/routers/finance.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk -""" - -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - -from odesk.namespaces import Namespace - - -class Finance(Namespace): - api_url = 'finance/' - version = 1 - - def get_withdrawal_methods(self): - """ - Retrieve a list of withdrawl available - """ - return self.get('withdrawals') - - def post_withdrawal(self, method_ref, amount): - """ - Post a withdrawl request - - Parameters - method_ref Withdrawl method reference - Amount Amount of withdrawl - """ - url = 'withdrawals/%s' % method_ref - data = {'amount': amount} - return self.post(url, data) diff --git a/odesk/routers/finreport.py b/odesk/routers/finreport.py index e43a78e..7a44928 100644 --- a/odesk/routers/finreport.py +++ b/odesk/routers/finreport.py @@ -1,25 +1,10 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - from odesk.namespaces import GdsNamespace -from odesk.utils import * class Finreports(GdsNamespace): diff --git a/odesk/routers/hr.py b/odesk/routers/hr.py index e0af937..685a624 100644 --- a/odesk/routers/hr.py +++ b/odesk/routers/hr.py @@ -1,25 +1,10 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - -from odesk.exceptions import APINotImplementedException from odesk.namespaces import Namespace -from odesk.utils import * class HR(Namespace): @@ -75,12 +60,6 @@ def get_company_teams(self, company_referece): result = self.get(url) return result['teams'] - def get_company_tasks(self, company_referece): - """ - API doesn't support this call yet - """ - raise APINotImplementedException("API doesn't support this call yet") - def get_company_users(self, company_referece, active=True): """ Retrieve a list of all users within the referenced company. @@ -122,12 +101,6 @@ def get_team(self, team_reference, include_users=False): #TODO: check how included users returned return result['team'] - def get_team_tasks(self, team_reference): - """ - API doesn't support this call yet - """ - raise APINotImplementedException("API doesn't support this call yet") - def get_team_users(self, team_reference, active=True): """ get_team_users(team_reference, active=True) @@ -160,12 +133,6 @@ def post_team_adjustment(self, team_reference, engagement_reference, result = self.post(url, data) return result['adjustment'] - '''task api''' - - def get_tasks(self): - "API doesn't support this call yet" - raise APINotImplementedException("API doesn't support this call yet") - '''userrole api''' def get_user_role(self, user_reference=None, team_reference=None, diff --git a/odesk/routers/mc.py b/odesk/routers/mc.py index 28c5474..b989622 100644 --- a/odesk/routers/mc.py +++ b/odesk/routers/mc.py @@ -1,23 +1,11 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging import urllib -import urllib2 - -try: - import json -except ImportError: - import simplejson as json - -from odesk.exceptions import * from odesk.namespaces import Namespace @@ -86,7 +74,7 @@ def get_thread_content(self, username, thread_id, paging_offset=0, result = self.get(url, data=data) return result["thread"] - def _generate_many_threads_url(self, url, threads_ids): + def _generate_many_threads_url(self, threads_ids): return ';'.join(urllib.quote(str(i)) for i in threads_ids) def put_threads_read_unread(self, username, thread_ids, read=True): @@ -103,8 +91,7 @@ def put_threads_read_unread(self, username, thread_ids, read=True): data = {'read': 'true'} else: data = {'read': 'false'} - result = self.put(self._generate_many_threads_url(url,\ - thread_ids), data=data) + result = self.put(self._generate_many_threads_url(thread_ids), data=data) return result def put_threads_read(self, username, thread_ids): @@ -144,8 +131,7 @@ def put_threads_starred_or_unstarred(self, username, thread_ids, else: data = {'starred': 'false'} - result = self.put(self._generate_many_threads_url(url,\ - thread_ids), data=data) + result = self.put(self._generate_many_threads_url(thread_ids), data=data) return result def put_threads_starred(self, username, thread_ids): @@ -187,8 +173,7 @@ def put_threads_deleted_or_undeleted(self, username, thread_ids, else: data = {'deleted': 'false'} - result = self.put(self._generate_many_threads_url(url, thread_ids), - data=data) + result = self.put(self._generate_many_threads_url(thread_ids), data=data) return result def put_threads_deleted(self, username, thread_ids): diff --git a/odesk/routers/oconomy.py b/odesk/routers/oconomy.py index a58bfda..bcd5732 100644 --- a/odesk/routers/oconomy.py +++ b/odesk/routers/oconomy.py @@ -1,25 +1,12 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib from datetime import date -import hashlib -import logging -import urllib -import urllib2 - -try: - import json -except ImportError: - import simplejson as json - -from odesk.exceptions import * from odesk.namespaces import GdsNamespace, NonauthGdsNamespace -from odesk.utils import * class OConomy(GdsNamespace): @@ -57,7 +44,6 @@ def get_summary(self, year=None, month=None): else: url = 'summary' result = self.get(url) - print url return result diff --git a/odesk/routers/provider.py b/odesk/routers/provider.py index 39b9a1d..1e85ea5 100644 --- a/odesk/routers/provider.py +++ b/odesk/routers/provider.py @@ -1,25 +1,10 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - from odesk.namespaces import Namespace -from odesk.utils import * class Provider(Namespace): @@ -106,11 +91,11 @@ def get_jobs(self, data=None, page_offset=0, page_size=20, order_by=None): return result['jobs'] def _get_resume_info(self, provider_ciphertext, info_type): - ''' + """ info_type can be one of (otherexp|skills|tests|certificates|employments|\ educations|projects) - ''' + """ strinfo = str(info_type) if strinfo not in self.resume_info_result_keys: raise ValueError('invalid info_type %s' % strinfo) @@ -119,52 +104,52 @@ def _get_resume_info(self, provider_ciphertext, info_type): result_key = self.resume_info_result_keys[strinfo] return result[result_key] - def _add_resume_info_item(self, provider_ciphertext, info_type,\ + def _add_resume_info_item(self, provider_ciphertext, info_type, \ item_data): - ''' + """ info_type can be one of (otherexp|skills|tests|certificates|employments|\ educations|projects - ''' + """ strinfo = str(info_type) if strinfo not in self.resume_info_result_keys: raise ValueError('invalid info_type %s' % strinfo) url = 'providers/%s/%s' % (str(provider_ciphertext), strinfo) return self.post(url, item_data) - def _update_resume_info_item(self, provider_ciphertext,\ + def _update_resume_info_item(self, provider_ciphertext, \ resource_id, info_type, item_data): - ''' + """ info_type can be one of (otherexp|skills|tests|certificates|\ employments|educations|projects - ''' + """ strinfo = str(info_type) if strinfo not in self.resume_info_result_keys: raise ValueError('invalid info_type %s' % strinfo) if resource_id is not None: - url = 'providers/%s/%s/%s' % (str(provider_ciphertext),\ + url = 'providers/%s/%s/%s' % (str(provider_ciphertext), \ str(resource_id), strinfo) else: - url = 'providers/%s/%s' % (str(provider_ciphertext),\ + url = 'providers/%s/%s' % (str(provider_ciphertext), \ strinfo) return self.post(url, item_data) - def _delete_resume_info_item(self, provider_ciphertext,\ + def _delete_resume_info_item(self, provider_ciphertext, \ resource_id, info_type): - ''' + """ info_type can be one of (otherexp|skills|tests|certificates|\ employments|educations|projects - ''' + """ strinfo = str(info_type) if strinfo not in self.resume_info_result_keys: raise ValueError('invalid info_type %s' % strinfo) if resource_id is not None: - url = 'providers/%s/%s/%s' % (str(provider_ciphertext),\ + url = 'providers/%s/%s/%s' % (str(provider_ciphertext), \ str(resource_id), strinfo) else: - url = 'providers/%s/%s' % (str(provider_ciphertext),\ + url = 'providers/%s/%s' % (str(provider_ciphertext), \ strinfo) return self.delete(url) @@ -178,40 +163,6 @@ def get_skills(self, provider_ciphertext): """ return self._get_resume_info(provider_ciphertext, 'skills') - def add_skill(self, provider_ciphertext, data): - """ - Add provider skills info - - Parameters - provider_ciphertext Provider cipher text (key) - data dict containing details of skill to add - """ - return self._add_resume_info_item(provider_ciphertext,\ - 'skills', data) - - def update_skill(self, provider_ciphertext, skill_id, data): - """ - Update provider skills info - - Parameters - provider_ciphertext Provider cipher text (key) - skill_id Resource id of the referenced skill - data dict containing details of skill to delete - """ - return self._update_resume_info_item(provider_ciphertext,\ - skill_id, 'skills', data) - - def delete_skill(self, provider_ciphertext, skill_id): - """ - Delete provider skills info - - Parameters - provider_ciphertext Provider cipher text (key) - skill_id Resource id of the referenced skill - """ - return self._delete_resume_info_item(provider_ciphertext,\ - skill_id, 'skills') - def get_quickinfo(self, provider_ciphertext): """ Retrieve provider 'quick info' @@ -229,7 +180,7 @@ def update_quickinfo(self, provider_ciphertext, data): provider_ciphertext Provider cipher text (key) data A dict containing updated 'quick info' """ - return self._update_resume_info_item(provider_ciphertext, None,\ + return self._update_resume_info_item(provider_ciphertext, None, \ 'quickinfo', data) def get_affiliates(self, affiliate_key): diff --git a/odesk/routers/task.py b/odesk/routers/task.py index 1c45446..a0e0817 100644 --- a/odesk/routers/task.py +++ b/odesk/routers/task.py @@ -1,22 +1,10 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - from odesk.namespaces import Namespace @@ -94,7 +82,7 @@ def get_team_tasks_full(self, company_id, team_id): company_id Company ID team_id Team ID """ - url = 'tasks/companies/%s/teams/%s/tasks/full_list' %\ + url = 'tasks/companies/%s/teams/%s/tasks/full_list' % \ (str(company_id), str(team_id)) result = self.get(url) return result["tasks"] or [] @@ -111,13 +99,15 @@ def get_user_tasks_full(self, company_id, team_id, user_id): team_id Team ID user_id User ID """ - url = 'tasks/companies/%s/teams/%s/users/%s/tasks/full_list' %\ + url = 'tasks/companies/%s/teams/%s/users/%s/tasks/full_list' % \ (str(company_id), str(team_id), str(user_id)) result = self.get(url) return result["tasks"] or [] def _generate_many_tasks_url(self, task_codes): - return ';'.join(urllib.quote(str(c)) for c in task_codes) + tasks = ';'.join(urllib.quote(str(c)) for c in task_codes) + #for correct work of oAuth signing + return urllib.quote(tasks) def get_company_specific_tasks(self, company_id, task_codes): """ @@ -141,7 +131,7 @@ def get_team_specific_tasks(self, company_id, team_id, task_codes): team_id Team ID task_codes Task codes (must be a list, even of 1 item) """ - url = 'tasks/companies/%s/teams/%s/tasks/%s' %\ + url = 'tasks/companies/%s/teams/%s/tasks/%s' % \ (str(company_id), str(team_id), self._generate_many_tasks_url(task_codes)) result = self.get(url) @@ -158,7 +148,7 @@ def get_user_specific_tasks(self, company_id, team_id, user_id, user_id User ID task_codes Task codes (must be a list, even of 1 item) """ - url = 'tasks/companies/%s/teams/%s/users/%s/tasks/%s' %\ + url = 'tasks/companies/%s/teams/%s/users/%s/tasks/%s' % \ (str(company_id), str(team_id), str(user_id), self._generate_many_tasks_url(task_codes)) result = self.get(url) @@ -317,7 +307,7 @@ def delete_user_task(self, company_id, team_id, user_id, task_codes): user_id User ID task_codes Task codes (must be a list, even of 1 item) """ - url = 'tasks/companies/%s/teams/%s/users/%s/tasks/%s' %\ + url = 'tasks/companies/%s/teams/%s/users/%s/tasks/%s' % \ (str(company_id), str(team_id), str(user_id), self. _generate_many_tasks_url(task_codes)) return self.delete(url, {}) diff --git a/odesk/routers/team.py b/odesk/routers/team.py index c255a32..b7ba651 100644 --- a/odesk/routers/team.py +++ b/odesk/routers/team.py @@ -1,23 +1,9 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - from odesk.namespaces import Namespace @@ -94,7 +80,7 @@ def update_snapshot(self, company_id, user_id, datetime=None, url = 'snapshots/%s/%s' % (str(company_id), str(user_id)) if datetime: url += '/%s' % datetime.isoformat() - return self.post(url, {'memo': memo}) + return self.put(url, {'memo': memo}) def delete_snapshot(self, company_id, user_id, datetime=None): """ @@ -135,21 +121,6 @@ def get_workdiaries(self, team_id, username, date=None): #not sure we need to return user return result['snapshots']['user'], snapshots - def get_stream(self, team_id, user_id=None,\ - from_ts=None): - """ - get_stream(team_id, user_id=None, from_ts=None) - """ - url = 'streams/%s' % (team_id) - if user_id: - url += '/%s' % (user_id) - if from_ts: - data = {'from_ts': from_ts} - else: - data = {} - result = self.get(url, data) - return result['streams']['snapshot'] - def get_teamrooms_2(self): """ Retrieve all teamrooms accessible to the authenticated user diff --git a/odesk/routers/ticket.py b/odesk/routers/ticket.py deleted file mode 100644 index 9254b05..0000000 --- a/odesk/routers/ticket.py +++ /dev/null @@ -1,79 +0,0 @@ -""" -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk -""" - -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - -from odesk.namespaces import Namespace - - -class Ticket(Namespace): - api_url = 'tickets/' - version = 1 - - def get_topics(self): - """ - Retrieve ticket topics - """ - url = 'topics' - result = self.get(url) - return result['topics'] - - def get_ticket(self, ticket_key): - """ - Retrieve details of a specific ticket - - Parameters - ticket_key Ticket key - """ - url = 'tickets/%s' % str(ticket_key) - result = self.get(url) - return result['ticket'] - - def post_new_ticket(self, message, topic_id='', topic_api_ref='', - email='', name=''): - """ - Post a new ticket - - Parameters - message - topic_id - topic_api_ref - email - name - """ - url = 'tickets' - data = {'message': message, - 'topic_id': topic_id, - 'topic_api_ref': topic_api_ref, - 'email': email, - } - result = self.post(url, data) - return result # TBD - - def post_reply_ticket(self, ticket_key, message): - """ - Post reply to a specific ticket - - Parameters - ticket_key Ticket key - message - """ - url = 'tickets/%s' % str(ticket_key) - data = {'message': message} - result = self.post(url, data) - return result # TBD diff --git a/odesk/routers/timereport.py b/odesk/routers/timereport.py index ec69482..72a3a2b 100644 --- a/odesk/routers/timereport.py +++ b/odesk/routers/timereport.py @@ -1,25 +1,10 @@ """ -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk +Python3 bindings to odesk API +python-odesk3 version 0.1 +(C) 2012 oDesk """ -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - from odesk.namespaces import GdsNamespace -from odesk.utils import * class TimeReport(GdsNamespace): diff --git a/odesk/routers/url.py b/odesk/routers/url.py deleted file mode 100644 index 2547c95..0000000 --- a/odesk/routers/url.py +++ /dev/null @@ -1,38 +0,0 @@ -""" -Python bindings to odesk API -python-odesk version 0.4 -(C) 2010-2011 oDesk -""" - -import cookielib -from datetime import date -import hashlib -import logging -import urllib -import urllib2 - - -try: - import json -except ImportError: - import simplejson as json - - -from odesk.namespaces import Namespace - - -class Url(Namespace): - api_url = 'shorturl/' - version = 1 - - def get_shorten(self, long_url): - url = 'shorten' - data = {'url': long_url} - result = self.get(url, data=data) - return result['short_url'] - - def get_expand(self, short_url): - url = 'expand' - data = {'url': short_url} - result = self.get(url, data=data) - return result['long_url'] diff --git a/odesk/tests.py b/odesk/tests.py index bbd1069..4da4ec1 100644 --- a/odesk/tests.py +++ b/odesk/tests.py @@ -12,7 +12,7 @@ from odesk.routers.team import Team from mock import Mock, patch -import urllib2 +import urllib2, urllib try: import json @@ -32,7 +32,7 @@ def test_signed_urlencode(): 'result': 'api_sig=ac0e1b26f401dd4a5ccbaf7f4ea86b2f&foo=bar&spam=42'}, } - for key in secret_data.keys(): + for key in list(secret_data.keys()): result = signed_urlencode(key, secret_data[key]['query']) assert secret_data[key]['result'] == result, \ " %s returned and should be %s" % (result, \ @@ -60,25 +60,25 @@ def test_base_client(): encodedkey = 'api_sig=8a0da3cab1dbf7451f38fb5f5aec129c&api_key=public&foo=bar&spam=42' assert urlresult == encodedkey, urlresult -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 return_sample_json(): - return json.dumps(sample_json_dict) + return json.dumps(sample_json_dict).encode("utf-8") def patched_urlopen(request, *args, **kwargs): @@ -103,19 +103,19 @@ def test_base_client_urlopen(): {'url': 'http://test.url', 'data': {}, 'method': 'POST', - 'result_data': 'api_sig=ba343f176db8166c4b7e88911e7e46ec&api_key=public', + 'result_data': b'api_sig=ba343f176db8166c4b7e88911e7e46ec&api_key=public', 'result_url': 'http://test.url', 'result_method': 'POST'}, {'url': 'http://test.url', 'data': {}, 'method': 'PUT', - 'result_data': 'api_sig=52cbaea073a5d47abdffc7fc8ccd839b&api_key=public&http_method=put', + 'result_data': b'api_sig=52cbaea073a5d47abdffc7fc8ccd839b&api_key=public&http_method=put', 'result_url': 'http://test.url', 'result_method': 'POST'}, {'url': 'http://test.url', 'data': {}, 'method': 'DELETE', - 'result_data': 'api_sig=8621f072b1492fbd164d808307ba72b9&api_key=public&http_method=delete', + 'result_data': b'api_sig=8621f072b1492fbd164d808307ba72b9&api_key=public&http_method=delete', 'result_url': 'http://test.url', 'result_method': 'POST'}, ] @@ -206,7 +206,7 @@ class NotJsonException(Exception): try: bc.read(url=test_url, format='yaml') raise NotJsonException() - except NotJsonException, e: + except NotJsonException as e: assert 0, "BaseClient.read() doesn't produce error on yaml format" except: pass @@ -218,44 +218,44 @@ class NotJsonException(Exception): #test get, 400 error try: result = base_client_read_400(bc=bc, url=test_url) - except HTTP400BadRequestError, e: + except HTTP400BadRequestError as e: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 400 code: " + str(e) #test get, 401 error try: result = base_client_read_401(bc=bc, url=test_url) - except HTTP401UnauthorizedError, e: + except HTTP401UnauthorizedError as e: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 401 code: " + str(e) #test get, 403 error try: result = base_client_read_403(bc=bc, url=test_url) - except HTTP403ForbiddenError, e: + except HTTP403ForbiddenError as e: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 403 code: " + str(e) #test get, 404 error try: result = base_client_read_404(bc=bc, url=test_url) - except HTTP404NotFoundError, e: + except HTTP404NotFoundError as e: pass - except Exception, e: + except Exception as e: assert 0, "Incorrect exception raised for 404 code: " + str(e) #test get, 500 error try: result = base_client_read_500(bc=bc, url=test_url) - except urllib2.HTTPError, e: + except urllib2.HTTPError as e: if e.code == 500: 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) @@ -329,7 +329,7 @@ def test_auth(): def return_frob_json(): - return json.dumps(frob_dict) + return json.dumps(frob_dict).encode("utf-8") def patched_urlopen_frob(request, *args, **kwargs): @@ -348,7 +348,7 @@ def test_auth_get_frob(): def return_token_json(): - return json.dumps(token_dict) + return json.dumps(token_dict).encode("utf-8") def patched_urlopen_token(request, *args, **kwargs): @@ -398,14 +398,14 @@ def test_check_token_false(): 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'} @@ -413,7 +413,7 @@ def test_check_token_false(): def return_teamrooms_json(): - return json.dumps(teamrooms_dict) + return json.dumps(teamrooms_dict).encode("utf-8") def patched_urlopen_teamrooms(request, *args, **kwargs): @@ -450,199 +450,153 @@ def test_team(): assert te.get_workdiaries(1, 1, 1) == (teamrooms_dict['snapshots']['user'], \ [teamrooms_dict['snapshots']['snapshot']]), te.get_workdiaries(1, 1, 1) - -stream_dict = {'streams': {'snapshot': [{u'uid': u'test', - u'portrait_50_img': u'http://www.odesk.com/att/~~test', - u'account_status': u'', - u'billing_status': u'billed.active', - u'screenshot_img_thmb': u'http://team.odesk.com/team/images.cache/test.jpg', - u'screenshot_url': u'https://team.odesk.com/team/scripts/image.jpg', - u'timezone': u'', u'digest': u'0', u'user_id': u'test', - u'company_id': u'test:test', u'report_url': u'http://team.url', - u'profile_url': u'http://www.odesk.com/users/~~test', - u'status': u'NORMAL', - u'report24_img': u'http://chart.apis.google.com/chart.png', - u'screenshot_img': u'http://team.odesk.com/team/images/test:test/test/2010/01/01/test.jpg', - u'memo': u'Bug 1: Test:Test', - u'time': u'test', u'cellts': u'test', - u'screenshot_img_med': u'http://team.odesk.com/team/scripts/image.jpg', - u'user': {u'first_name': u'Test', u'last_name': u'Test', - u'uid': u'test', u'timezone_offset': u'10000', u'creation_time': u'', - u'mail': u'test@odesk.com', u'timezone': u'Europe/Athens', - u'messenger_id': u'', u'messenger_type': u''}, u'computer_name': u'laptop', - u'active_window_title': u'2010-01-01 - Google Chrome', - u'task': {u'code': u'484', u'id': u'{type=bugzilla,cny=test:test,code=1}', - u'description': u'Bug 1: Test: Test'}, - u'keyboard_events_count': u'1', u'mouse_events_count': u'1', u'activity': u'1', - u'client_version': u'Linux/2.0.0', u'screenshot_img_lrg': u'http://test.com', - u'portrait_img': u'http://www.test.com'}]}} - - -def return_stream_json(): - return json.dumps(stream_dict) - - -def patched_urlopen_stream(request, *args, **kwargs): - request.read = return_stream_json - return request - - -@patch('urllib2.urlopen', patched_urlopen_stream) -def test_stream(): - te = Team(get_client()) - - #test get_stream - assert te.get_stream('test', 'test') == stream_dict['streams']['snapshot'], \ - te.get_stream('test', 'test') - - -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', } - -candidacy_stats = {u'job_application_quota': u'20', - u'job_application_quota_remaining': u'20', - u'number_of_applications': u'2', - u'number_of_interviews': u'3', - u'number_of_invites': u'0', - u'number_of_offers': u'0'} - -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, - u'candidacy_stats': candidacy_stats} +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', } + +candidacy_stats = {'job_application_quota': '20', + 'job_application_quota_remaining': '20', + 'number_of_applications': '2', + 'number_of_interviews': '3', + 'number_of_invites': '0', + 'number_of_offers': '0'} + +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, + 'candidacy_stats': candidacy_stats} def return_hr_json(): - return json.dumps(hr_dict) + return json.dumps(hr_dict).encode("utf-8") def patched_urlopen_hr(request, *args, **kwargs): @@ -655,17 +609,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('urllib2.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('urllib2.urlopen', patched_urlopen_hr) @@ -683,76 +637,31 @@ def test_get_hrv2_company_users(): assert hr.get_company_users(1, False) == hr_dict['users'], \ hr.get_company_users(1, False) - -@patch('urllib2.urlopen', patched_urlopen_hr) -def test_get_hrv2_company_tasks(): - hr = get_client().hr - #test get_company_tasks - try: - assert hr.get_company_tasks(1) == hr_dict['tasks'], \ - hr.get_company_tasks(1) - except APINotImplementedException, e: - pass - except Exception, e: - print e - assert 0, "APINotImplementedException not raised" - - @patch('urllib2.urlopen', patched_urlopen_hr) 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('urllib2.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) -@patch('urllib2.urlopen', patched_urlopen_hr) -def test_get_hrv2_team_tasks(): - hr = get_client().hr - #test get_team_tasks - try: - assert hr.get_team_tasks(1) == hr_dict['tasks'], hr.get_team_tasks(1) - except APINotImplementedException, e: - pass - except: - assert 0, "APINotImplementedException not raised" - - -@patch('urllib2.urlopen', patched_urlopen_hr) -def test_get_hrv2_userroles(): - hr = get_client().hr - #test get_user_role - assert hr.get_user_role(user_reference=1) == hr_dict['userroles'], \ - hr.get_user_role(user_reference=1) - assert hr.get_user_role(team_reference=1) == hr_dict['userroles'], \ - hr.get_user_role(team_reference=1) - assert hr.get_user_role() == hr_dict['userroles'], hr.get_user_role() - - try: - assert hr.get_tasks() == hr_dict['tasks'], hr.get_tasks() - except APINotImplementedException, e: - pass - except: - assert 0, "APINotImplementedException not raised" - - @patch('urllib2.urlopen', patched_urlopen_hr) def test_get_hrv2_jobs(): hr = get_client().hr #test get_jobs - assert hr.get_jobs() == hr_dict[u'jobs'], hr.get_jobs() - assert hr.get_job(1) == hr_dict[u'job'], hr.get_job(1) + assert hr.get_jobs() == hr_dict['jobs'], hr.get_jobs() + assert hr.get_job(1) == hr_dict['job'], hr.get_job(1) assert hr.update_job(1, {'status': 'filled'}) == hr_dict, hr.update_job(1, {'status': 'filled'}) assert hr.delete_job(1, 41) == hr_dict, hr.delete_job(1, 41) @@ -761,23 +670,23 @@ def test_get_hrv2_jobs(): def test_get_hrv2_offers(): hr = get_client().hr #test get_offers - assert hr.get_offers() == hr_dict[u'offers'], hr.get_offers() - assert hr.get_offer(1) == hr_dict[u'offer'], hr.get_offer(1) + assert hr.get_offers() == hr_dict['offers'], hr.get_offers() + assert hr.get_offer(1) == hr_dict['offer'], hr.get_offer(1) @patch('urllib2.urlopen', patched_urlopen_hr) def test_get_hrv2_engagements(): hr = get_client().hr #test get_engagements - assert hr.get_engagements() == hr_dict[u'engagements'], hr.get_engagements() - assert hr.get_engagement(1) == hr_dict[u'engagement'], hr.get_engagement(1) + assert hr.get_engagements() == hr_dict['engagements'], hr.get_engagements() + assert hr.get_engagement(1) == hr_dict['engagement'], hr.get_engagement(1) -adjustments = {u'adjustment': {u'reference': '100'}} +adjustments = {'adjustment': {'reference': '100'}} def return_hradjustment_json(): - return json.dumps(adjustments) + return json.dumps(adjustments).encode("utf-8") def patched_urlopen_hradjustment(request, *args, **kwargs): @@ -790,7 +699,7 @@ def test_hrv2_post_adjustment(): hr = get_client().hr result = hr.post_team_adjustment(1, 2, 100000, 'test', 'test note') - assert result == adjustments[u'adjustment'], result + assert result == adjustments['adjustment'], result @patch('urllib2.urlopen', patched_urlopen_hr) @@ -802,27 +711,27 @@ def test_get_hrv2_candidacy_stats(): 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'}, @@ -838,7 +747,7 @@ def test_get_hrv2_candidacy_stats(): def return_provider_json(): - return json.dumps(provider_dict) + return json.dumps(provider_dict).encode("utf-8") def patched_urlopen_provider(request, *args, **kwargs): @@ -872,15 +781,6 @@ def test_provider(): assert pr.get_skills(1) == provider_dict['skills'], \ pr.get_skills(1) - assert pr.add_skill(1, {'skill': 'skill'}) == provider_dict, \ - pr.add_skill(1, {'skill': 'skill'}) - - assert pr.update_skill(1, 1, {'skill': 'skill'}) == provider_dict, \ - pr.update_skill(1, 1, {'skill': 'skill'}) - - assert pr.delete_skill(1, 1) == provider_dict, \ - pr.delete_skill(1, 1) - assert pr.get_quickinfo(1) == provider_dict['quick_info'], \ pr.get_quickinfo(1) @@ -891,22 +791,22 @@ def test_provider(): assert result == provider_dict['profile'] -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 return_trays_json(): - return json.dumps(trays_dict) + return json.dumps(trays_dict).encode("utf-8") def patched_urlopen_trays(request, *args, **kwargs): @@ -932,7 +832,7 @@ def test_get_trays(): def return_tray_content_json(): - return json.dumps(tray_content_dict) + return json.dumps(tray_content_dict).encode("utf-8") def patched_urlopen_tray_content(request, *args, **kwargs): @@ -956,7 +856,7 @@ def test_get_tray_content(): def return_thread_content_json(): - return json.dumps(thread_content_dict) + return json.dumps(thread_content_dict).encode("utf-8") def patched_urlopen_thread_content(request, *args, **kwargs): @@ -980,7 +880,7 @@ def test_get_thread_content(): def return_read_thread_content_json(): - return json.dumps(read_thread_content_dict) + return json.dumps(read_thread_content_dict).encode("utf-8") def patched_urlopen_read_thread_content(request, *args, **kwargs): @@ -1047,28 +947,28 @@ 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 return_read_timereport_json(*args, **kwargs): - return json.dumps(timereport_dict) + return json.dumps(timereport_dict).encode("utf-8") def patched_urlopen_timereport_content(request, *args, **kwargs): @@ -1117,28 +1017,28 @@ 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 return_read_fin_report_json(*args, **kwargs): - return json.dumps(fin_report_dict) + return json.dumps(fin_report_dict).encode("utf-8") def patched_urlopen_fin_report_content(request, *args, **kwargs): @@ -1252,12 +1152,12 @@ def test_get_version(): assert get_version() == '1.2.3 pre-alpha', get_version() -task_dict = {u'tasks': 'task1' +task_dict = {'tasks': 'task1' } def return_task_dict_json(*args, **kwargs): - return json.dumps(task_dict) + return json.dumps(task_dict).encode("utf-8") def patched_urlopen_task(request, *args, **kwargs): @@ -1449,33 +1349,33 @@ def test_gds_namespace(): gds.urlopen('test.url', {}, 'POST') -oconomy_dict = {u'table': - {u'rows': - [{u'c': [{u'v': u'Administrative Support'}, - {u'v': u'2787297.31'}]}, - {u'c': [{u'v': u'Business Services'}, - {u'v': u'1146857.51'}]}, - {u'c': [{u'v': u'Customer Service'}, - {u'v': u'1072926.55'}]}, - {u'c': [{u'v': u'Design & Multimedia'}, - {u'v': u'1730094.73'}]}, - {u'c': [{u'v': u'Networking & Information Systems'}, - {u'v': u'690526.57'}]}, - {u'c': [{u'v': u'Sales & Marketing'}, - {u'v': u'3232511.54'}]}, - {u'c': [{u'v': u'Software Development'}, - {u'v': u'6826354.60'}]}, - {u'c': [{u'v': u'Web Development'}, - {u'v': u'15228679.46'}]}, - {u'c': [{u'v': u'Writing & Translation'}, - {u'v': u'2257654.76'}]}], - u'cols': - [{u'type': u'string', u'label': u'category'}, - {u'type': u'number', u'label': u'amount'}]}} +oconomy_dict = {'table': + {'rows': + [{'c': [{'v': 'Administrative Support'}, + {'v': '2787297.31'}]}, + {'c': [{'v': 'Business Services'}, + {'v': '1146857.51'}]}, + {'c': [{'v': 'Customer Service'}, + {'v': '1072926.55'}]}, + {'c': [{'v': 'Design & Multimedia'}, + {'v': '1730094.73'}]}, + {'c': [{'v': 'Networking & Information Systems'}, + {'v': '690526.57'}]}, + {'c': [{'v': 'Sales & Marketing'}, + {'v': '3232511.54'}]}, + {'c': [{'v': 'Software Development'}, + {'v': '6826354.60'}]}, + {'c': [{'v': 'Web Development'}, + {'v': '15228679.46'}]}, + {'c': [{'v': 'Writing & Translation'}, + {'v': '2257654.76'}]}], + 'cols': + [{'type': 'string', 'label': 'category'}, + {'type': 'number', 'label': 'amount'}]}} def return_read_oconomy_json(*args, **kwargs): - return json.dumps(oconomy_dict) + return json.dumps(oconomy_dict).encode("utf-8") def patched_urlopen_oconomy_content(request, *args, **kwargs): @@ -1548,13 +1448,13 @@ def test_oauth_full_url(): def patched_httplib2_request(*args, **kwargs): return {'status': '200'},\ - 'oauth_callback_confirmed=1&oauth_token=709d434e6b37a25c50e95b0e57d24c46&oauth_token_secret=193ef27f57ab4e37' + b'oauth_callback_confirmed=1&oauth_token=709d434e6b37a25c50e95b0e57d24c46&oauth_token_secret=193ef27f57ab4e37' @patch('httplib2.Http.request', patched_httplib2_request) def test_oauth_get_request_token(): oa = setup_oauth() - assert oa.get_request_token() == ('709d434e6b37a25c50e95b0e57d24c46',\ - '193ef27f57ab4e37') + assert oa.get_request_token() == (b'709d434e6b37a25c50e95b0e57d24c46',\ + b'193ef27f57ab4e37') @patch('httplib2.Http.request', patched_httplib2_request) def test_oauth_get_authorize_url(): @@ -1566,7 +1466,7 @@ def test_oauth_get_authorize_url(): def patched_httplib2_access(*args, **kwargs): return {'status': '200'},\ - 'oauth_token=aedec833d41732a584d1a5b4959f9cd6&oauth_token_secret=9d9cccb363d2b13e' + b'oauth_token=aedec833d41732a584d1a5b4959f9cd6&oauth_token_secret=9d9cccb363d2b13e' @patch('httplib2.Http.request', patched_httplib2_access) def test_oauth_get_access_token(): @@ -1574,4 +1474,4 @@ def test_oauth_get_access_token(): oa.request_token = '709d434e6b37a25c50e95b0e57d24c46' oa.request_token_secret = '193ef27f57ab4e37' assert oa.get_access_token('9cbcbc19f8acc2d85a013e377ddd4118') ==\ - ('aedec833d41732a584d1a5b4959f9cd6', '9d9cccb363d2b13e') + (b'aedec833d41732a584d1a5b4959f9cd6', b'9d9cccb363d2b13e') diff --git a/requirements.py b/requirements.py index cc5559a..9e1c3f8 100644 --- a/requirements.py +++ b/requirements.py @@ -1,3 +1,3 @@ nose mock -oauth2 +https://github.com/hades/python-oauth2/tarball/python3#egg=oauth2 diff --git a/setup.py b/setup.py index 56c9541..e98b0bf 100644 --- a/setup.py +++ b/setup.py @@ -1,22 +1,31 @@ import os +import sys +if sys.version_info[0] == 3: + import setuptools + if setuptools.__version__ < "0.7": + print("This setup.py requeries setuptools>=0.7\n") + sys.exit(0) from setuptools import setup, find_packages readme = open(os.path.join(os.path.dirname(__file__), 'README')) README = readme.read() readme.close() -version = __import__('odesk').get_version() +version = "0.1" -setup(name='python-odesk', +setup(name='python-odesk3', version=version, - description='Python bindings to oDesk API', + description='Python3 bindings to oDesk API', long_description=README, author='oDesk', author_email='python@odesk.com', maintainer='Volodymyr Hotsyk', + use_2to3 = True, + use_2to3_fixers = ['fixers'], maintainer_email='gotsyk@gmail.com', - install_requires=['oauth2',], + install_requires=['oauth2', 'mock', 'nose'], + dependency_links = ['https://github.com/hades/python-oauth2/tarball/python3#egg=oauth2',], packages=find_packages(), license = 'BSD', download_url ='http://github.com/odesk/python-odesk',