From b346416d6033a82980fa8180530a82a879782b5f Mon Sep 17 00:00:00 2001 From: andresgz Date: Tue, 17 Nov 2015 16:35:06 -0500 Subject: [PATCH 1/6] Prepare project for packaging --- .gitignore | 13 ++++++++++++- setup.py | 17 +++++++++++++++++ tests/tests_live.py | 4 ++-- tests/tests_offline.py | 5 +++-- toggl/__init__.py | 1 + api_client.py => toggl/api_client.py | 0 6 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 setup.py create mode 100644 toggl/__init__.py rename api_client.py => toggl/api_client.py (100%) diff --git a/.gitignore b/.gitignore index ff88fc0..387e025 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,13 @@ *.pyc -tests_live_config.json \ No newline at end of file +tests_live_config.json + +# Setuptools distribution folder. +/dist/ +/build/ + +# Python egg metadata, regenerated from source files by setuptools. +/*.egg-info + +# Others +*.swp +.DS_Store \ No newline at end of file diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..aae3760 --- /dev/null +++ b/setup.py @@ -0,0 +1,17 @@ +from setuptools import setup + + +setup(name='python-toggl', + version='0.1.0', + description='Python Wrapper for Toggl API', + url='https://github.com/swappsco/python-toggl', + author='mechastorm', + author_email='dev@swapps.co', + license='MIT', + packages=['toggl'], + install_requires=[ + 'requests', + ], + test_suite='nose.collector', + tests_require=['nose', 'httpretty'], + zip_safe=False) diff --git a/tests/tests_live.py b/tests/tests_live.py index 6d82ee5..3d63b11 100644 --- a/tests/tests_live.py +++ b/tests/tests_live.py @@ -1,6 +1,6 @@ import unittest import json -from ..api_client import TogglClientApi +from toggl.api_client import TogglClientApi class TogglClientApiLiveTests(unittest.TestCase): @@ -21,7 +21,7 @@ def tearDown(self): def test_api_client_instance_created(self): self.assertNotEqual(self.api, None) - + def test_valid_toggl_base_url(self): self.assertEqual(self.api.api_base_url, 'https://www.toggl.com/api/v8') diff --git a/tests/tests_offline.py b/tests/tests_offline.py index cdbcd73..4107bda 100644 --- a/tests/tests_offline.py +++ b/tests/tests_offline.py @@ -1,7 +1,8 @@ import unittest import httpretty import json -from ..api_client import TogglClientApi +from toggl.api_client import TogglClientApi + class ToogleClientApiTests(unittest.TestCase): @@ -33,7 +34,7 @@ def tearDown(self): httpretty.disable() httpretty.reset() - def load_json_file(self, location, base_path='json_responses'): + def load_json_file(self, location, base_path='tests/json_responses'): file_contents = open(base_path+'/'+location+'.json') json_data = json.load(file_contents) file_contents.close() diff --git a/toggl/__init__.py b/toggl/__init__.py new file mode 100644 index 0000000..15a7b89 --- /dev/null +++ b/toggl/__init__.py @@ -0,0 +1 @@ +from toggl_api import api_client \ No newline at end of file diff --git a/api_client.py b/toggl/api_client.py similarity index 100% rename from api_client.py rename to toggl/api_client.py From 3e2f9d9e58f77e667901b1876be6a3a96f6c39ae Mon Sep 17 00:00:00 2001 From: andresgz Date: Tue, 17 Nov 2015 21:39:50 -0500 Subject: [PATCH 2/6] Implement get-projects method --- setup.py | 2 +- toggl/__init__.py | 2 +- toggl/api_client.py | 8 ++++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index aae3760..9a8b45f 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup(name='python-toggl', - version='0.1.0', + version='0.1.1', description='Python Wrapper for Toggl API', url='https://github.com/swappsco/python-toggl', author='mechastorm', diff --git a/toggl/__init__.py b/toggl/__init__.py index 15a7b89..220455b 100644 --- a/toggl/__init__.py +++ b/toggl/__init__.py @@ -1 +1 @@ -from toggl_api import api_client \ No newline at end of file +from toggl import api_client \ No newline at end of file diff --git a/toggl/api_client.py b/toggl/api_client.py index 77312d0..29662df 100644 --- a/toggl/api_client.py +++ b/toggl/api_client.py @@ -47,10 +47,13 @@ def get_workspace_by_name(self, name): return workspace_found def get_workspaces(self): - return self.query('/workspaces'); + return self.query('/workspaces') + + def get_projects(self, workspace_id): + return self.query('/workspaces/%i/projects' % workspace_id) def get_workspace_members(self, workspace_id): - response = self.query('/workspaces/'+str(workspace_id)+'/workspace_users'); + response = self.query('/workspaces/'+str(workspace_id)+'/workspace_users') return response """ @@ -100,6 +103,7 @@ def _query(self, base_url, url, params, method): @staticmethod def _do_get_query(url, headers, auth, params): + print url response = requests.get(url, headers=headers, auth=auth, params=params) return response \ No newline at end of file From cfd1e2f222a0d943f28536d8587ed096d5133677 Mon Sep 17 00:00:00 2001 From: andresgz Date: Wed, 18 Nov 2015 19:26:06 -0500 Subject: [PATCH 3/6] Implement method to get time reports --- setup.py | 2 +- toggl/api_client.py | 29 ++++++++++++++++++++++++++--- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/setup.py b/setup.py index 9a8b45f..f35035b 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ setup(name='python-toggl', - version='0.1.1', + version='0.1.2', description='Python Wrapper for Toggl API', url='https://github.com/swappsco/python-toggl', author='mechastorm', diff --git a/toggl/api_client.py b/toggl/api_client.py index 29662df..74b4c47 100644 --- a/toggl/api_client.py +++ b/toggl/api_client.py @@ -1,5 +1,5 @@ import requests - +from datetime import date class TogglClientApi: @@ -26,6 +26,8 @@ def __init__(self, credentials): self.api_report_base_url = self.build_api_url(self.credentials['base_url_report'], self.credentials['ver_report']) self.api_token = self.credentials['token'] self.api_username = self.credentials['username'] + self.user_agent = self.credentials['user_agent'] + self.workspace_id = int(self.credentials['workspace_id']) return @staticmethod @@ -49,8 +51,8 @@ def get_workspace_by_name(self, name): def get_workspaces(self): return self.query('/workspaces') - def get_projects(self, workspace_id): - return self.query('/workspaces/%i/projects' % workspace_id) + def get_projects(self): + return self.query('/workspaces/%i/projects' % self.workspace_id) def get_workspace_members(self, workspace_id): response = self.query('/workspaces/'+str(workspace_id)+'/workspace_users') @@ -81,6 +83,26 @@ def get_user_hours_range(self, user_agent, workspace_id, user_id, start_date, en return time_total + """ + @param start_date datetime.date() + @param end_date datetime.date() + """"" + def get_project_times(self, project_id, start_date, end_date): + params = { + 'workspace_id': self.workspace_id, + 'project_ids': project_id, + 'since': start_date.strftime('%Y-%m-%d'), + 'until': end_date.strftime('%Y-%m-%d'), + 'user_agent': self.user_agent, + 'grouping': 'users', + 'subgrouping': 'projects' + } + time_entries_response = self.query_report('/details', params) + + json_response = time_entries_response.json() + + return json_response + def query_report(self, url, params={}, method='GET'): return self._query(self.api_report_base_url, url, params, method) @@ -104,6 +126,7 @@ def _query(self, base_url, url, params, method): @staticmethod def _do_get_query(url, headers, auth, params): print url + print params response = requests.get(url, headers=headers, auth=auth, params=params) return response \ No newline at end of file From 73ef728d6d7880ea5714626b5ca887f255e1444f Mon Sep 17 00:00:00 2001 From: andresgz Date: Wed, 18 Nov 2015 19:43:44 -0500 Subject: [PATCH 4/6] Update documentation and setup.py information --- README.md | 6 +++++- setup.py | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7f188a2..b296b0f 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,11 @@ There is already a similar library, [toggl_target](https://github.com/mos3abof/t # Usage -The library is currently not in a Python PIP package yet. For now simply download to a location of your choice and do the following. +## Pypi Package + pip install python-toggl + +## Manual installation +Download to a location of your choice and do the following. ```python diff --git a/setup.py b/setup.py index f35035b..fa3f217 100644 --- a/setup.py +++ b/setup.py @@ -2,9 +2,9 @@ setup(name='python-toggl', - version='0.1.2', + version='0.1.3', description='Python Wrapper for Toggl API', - url='https://github.com/swappsco/python-toggl', + url='https://github.com/swappsco/toggl-python-api-client', author='mechastorm', author_email='dev@swapps.co', license='MIT', From 5a4dfd1b92e47eaf8eaa386eb0cefbf7edd5c64d Mon Sep 17 00:00:00 2001 From: andresgz Date: Wed, 18 Nov 2015 19:47:00 -0500 Subject: [PATCH 5/6] Add readme to setup.py --- setup.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/setup.py b/setup.py index fa3f217..7511863 100644 --- a/setup.py +++ b/setup.py @@ -1,9 +1,14 @@ from setuptools import setup +def readme(): + with open('README.md') as f: + return f.read() + setup(name='python-toggl', version='0.1.3', description='Python Wrapper for Toggl API', + long_description=readme(), url='https://github.com/swappsco/toggl-python-api-client', author='mechastorm', author_email='dev@swapps.co', From e43941e0d695639e73f0688696fa1daf21cbf291 Mon Sep 17 00:00:00 2001 From: andresgz Date: Wed, 18 Nov 2015 19:52:28 -0500 Subject: [PATCH 6/6] Add RST documentation for Pypi --- README.rst | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 4 +-- 2 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 README.rst diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..1a17825 --- /dev/null +++ b/README.rst @@ -0,0 +1,99 @@ +toggl-python-api-client +======================= + +`Toggl `__ is an "insanely simple time tracking" +service. + +This specific library is a Python-based REST client to interface with +the Toggle API utilizing +`requests `__. + +This library is a pure api client to help other python apps interface +with Toggl. I created this project primarily to help with a bigger +internal project that I am doing at work while at the same time getting +my feet wet in Python. + +Others out there +================ + +There is already a similar library, +`toggl\_target `__ though it +is more of an application and the client api is not separate repo. Some +ideas/concepts on the client api were taken from there but I had needed +a client api only to help interface with my bigger app. + +Usage +===== + +Pypi Package +------------ + +:: + + pip install python-toggl + +Manual installation +------------------- + +Download to a location of your choice and do the following. + +.. code:: python + + + from toggl-python-api-client.api_client import TogglClientApi + + settings = { + 'token': 'xxx', + 'user_agent': 'your app name' + } + toggle_client = TogglClientApi(settings) + + response = toggle_client.get_workspaces() + +Dependencies +============ + +- Python 2.7 onwards +- `requests `__ + +Tests Dependencies +------------------ + +To run the tests, you will need the following packages + +- unittest +- json +- `httpretty `__ + +Tests +===== + +Tests created under ``/tests`` are primarily integration tests and are +not strictly unit tests. They consists of an offline and online(live) +test. + +Offline +------- + +``tests/tests_offline.py`` + +These tests are for the logic of the api client. They do not connect to +the actual Toggl servers - instead use +`httpretty `__ to mock the +responses. Sample responses are included in ``tests/json_responses`` and +are based on Toggle responses for V8 of the main api and V2 of the +report api. + +Online/Live +----------- + +``tests/tests_live.py`` + +These tests are to check the connections to Toggl's API and to ensure +that the client is handling the live responses from Toggl as expected. + +To avoid adding sensitive data to version control, no api credentials +have been included. To enable live tests, - make a copy of +``tests/tests_live_config.json.sample`` as +``tests/tests_live_config.json`` - update the settings on +``tests/tests_live_config.json`` as needed \ No newline at end of file diff --git a/setup.py b/setup.py index 7511863..4c3152f 100644 --- a/setup.py +++ b/setup.py @@ -2,11 +2,11 @@ def readme(): - with open('README.md') as f: + with open('README.rst') as f: return f.read() setup(name='python-toggl', - version='0.1.3', + version='0.1.4', description='Python Wrapper for Toggl API', long_description=readme(), url='https://github.com/swappsco/toggl-python-api-client',