3
3
"""
4
4
import requests
5
5
import urllib .parse
6
+ from datetime import datetime
7
+ from requests .models import Response
6
8
from pyclickup .globals import __version__ , API_URL , LIBRARY , TEST_TOKEN , TEST_API_URL
7
9
from pyclickup .models import User , Task , Team
8
10
from pyclickup .models .error import RateLimited
9
11
from pyclickup .utils .text import datetime_to_ts , filter_locals
10
-
11
-
12
- def test_client ():
13
- """returns a test client"""
14
- return ClickUp (TEST_TOKEN , api_url = TEST_API_URL , debug = True )
12
+ from typing import Any , Dict , List , Optional , Union # noqa
15
13
16
14
17
15
class ClickUp :
@@ -26,7 +24,13 @@ class ClickUp:
26
24
"assignees" ,
27
25
]
28
26
29
- def __init__ (self , token , api_url = API_URL , cache = True , debug = False ):
27
+ def __init__ (
28
+ self ,
29
+ token : str ,
30
+ api_url : str = API_URL ,
31
+ cache : bool = True ,
32
+ debug : bool = False ,
33
+ ) -> None :
30
34
"""creates a new client"""
31
35
if not token :
32
36
raise Exception ("no token specified!" )
@@ -37,11 +41,11 @@ def __init__(self, token, api_url=API_URL, cache=True, debug=False):
37
41
self .debug = debug
38
42
39
43
# cache
40
- self ._user = None
41
- self ._teams = None
44
+ self ._user = None # type: Optional[User]
45
+ self ._teams = None # type: Optional[List[Team]]
42
46
43
47
@property
44
- def headers (self ):
48
+ def headers (self ) -> dict :
45
49
"""forms the headers required for the API calls"""
46
50
return {
47
51
"Accept" : "application/json" ,
@@ -51,30 +55,36 @@ def headers(self):
51
55
}
52
56
53
57
@property
54
- def user (self ):
58
+ def user (self ) -> User :
55
59
"""get the user associated with this token"""
56
60
if not self ._user or not self .cache :
57
61
self ._user = User (self .get ("user" ), client = self )
58
62
return self ._user
59
63
60
64
@property
61
- def teams (self ):
65
+ def teams (self ) -> List [ Team ] :
62
66
"""get authorized teams"""
63
67
if not self ._teams or not self .cache :
64
- self ._teams = [Team (x , client = self ) for x in self .get ("team" )["teams" ]]
68
+ teams_data = self .get ("team" )
69
+ if not isinstance (teams_data , dict ):
70
+ raise Exception ("invalid response while looking up teams" )
71
+ self ._teams = [Team (x , client = self ) for x in teams_data ["teams" ]]
65
72
return self ._teams
66
73
67
- def get_team_by_id (self , team_id ) :
74
+ def get_team_by_id (self , team_id : str ) -> Team :
68
75
"""given an team_id, return the team if it exists"""
69
- return Team (self .get ("team/{}" .format (team_id ))["team" ], client = self )
76
+ team_data = self .get ("team/{}" .format (team_id ))
77
+ if not isinstance (team_data , dict ):
78
+ raise Exception ("no team found" )
79
+ return Team (team_data ["team" ], client = self )
70
80
71
- def _log (self , * args ) :
81
+ def _log (self , * args : Any ) -> None :
72
82
"""logging method"""
73
83
if not self .debug :
74
84
return
75
85
print (* args )
76
86
77
- def _req (self , path , method = "get" , ** kwargs ) :
87
+ def _req (self , path : str , method : str = "get" , ** kwargs : Any ) -> Response :
78
88
"""requests wrapper"""
79
89
full_path = urllib .parse .urljoin (self .api_url , path )
80
90
self ._log ("[{}]: {}" .format (method .upper (), full_path ))
@@ -83,39 +93,48 @@ def _req(self, path, method="get", **kwargs):
83
93
raise RateLimited ()
84
94
return request
85
95
86
- def get (self , path , ** kwargs ):
96
+ def get (
97
+ self , path : str , raw : bool = False , ** kwargs : Any
98
+ ) -> Union [list , dict , Response ]:
87
99
"""makes a get request to the API"""
88
- return self ._req (path , ** kwargs ).json ()
100
+ request = self ._req (path , ** kwargs )
101
+ return request if raw else request .json ()
89
102
90
- def post (self , path , ** kwargs ):
103
+ def post (
104
+ self , path : str , raw : bool = False , ** kwargs : Any
105
+ ) -> Union [list , dict , Response ]:
91
106
"""makes a post request to the API"""
92
- return self ._req (path , method = "post" , ** kwargs ).json ()
107
+ request = self ._req (path , method = "post" , ** kwargs )
108
+ return request if raw else request .json ()
93
109
94
- def put (self , path , ** kwargs ):
110
+ def put (
111
+ self , path : str , raw : bool = False , ** kwargs : Any
112
+ ) -> Union [list , dict , Response ]:
95
113
"""makes a put request to the API"""
96
- return self ._req (path , method = "put" , ** kwargs ).json ()
114
+ request = self ._req (path , method = "put" , ** kwargs )
115
+ return request if raw else request .json ()
97
116
98
117
def _get_tasks (
99
118
self ,
100
- team_id ,
101
- page = None , # integer - it appears to fetch 100 at a time
102
- order_by = None , # string, [id, created, updated, due_date]
103
- reverse = None , # bool
104
- subtasks = None , # bool
105
- space_ids = None , # List
106
- project_ids = None , # List
107
- list_ids = None , # List
108
- statuses = None , # List
109
- include_closed = False , # bool
110
- assignees = None , # List
111
- due_date_gt = None , # integer, posix time
112
- due_date_lt = None , # integer, posix time
113
- date_created_gt = None , # integer, posix time
114
- date_created_lt = None , # integer, posix time
115
- date_updated_gt = None , # integer, posix time
116
- date_updated_lt = None , # integer, posix time
117
- ** kwargs
118
- ):
119
+ team_id : str ,
120
+ page : int = None , # integer - it appears to fetch 100 at a time
121
+ order_by : str = None , # string, [id, created, updated, due_date]
122
+ reverse : bool = None , # bool
123
+ subtasks : bool = None , # bool
124
+ space_ids : list = None , # List
125
+ project_ids : list = None , # List
126
+ list_ids : list = None , # List
127
+ statuses : list = None , # List
128
+ include_closed : bool = False , # bool
129
+ assignees : list = None , # List
130
+ due_date_gt : int = None , # integer, posix time
131
+ due_date_lt : int = None , # integer, posix time
132
+ date_created_gt : int = None , # integer, posix time
133
+ date_created_lt : int = None , # integer, posix time
134
+ date_updated_gt : int = None , # integer, posix time
135
+ date_updated_lt : int = None , # integer, posix time
136
+ ** kwargs : Any
137
+ ) -> List [ Task ] :
119
138
"""fetches the tasks according to the given options"""
120
139
params = filter_locals (locals (), extras = ["team_id" ])
121
140
@@ -132,31 +151,40 @@ def _get_tasks(
132
151
for x in params
133
152
]
134
153
path = "team/{}/task?{}" .format (team_id , "&" .join (options ))
135
- return [Task (x , client = self ) for x in self .get (path )["tasks" ]]
136
-
137
- def _get_all_tasks (self , team_id , ** kwargs ):
154
+ task_list = self .get (path )
155
+ if not isinstance (task_list , dict ):
156
+ return []
157
+ return [Task (x , client = self ) for x in task_list ["tasks" ]]
158
+
159
+ def _get_all_tasks (
160
+ self , team_id : str , page_limit : int = - 1 , ** kwargs : Any
161
+ ) -> List [Task ]:
138
162
"""get all tasks wrapper"""
139
- tasks = []
163
+ tasks = [] # type: List[Task]
140
164
page_count = 0
141
165
task_page = self ._get_tasks (team_id , page = page_count , ** kwargs )
142
- while task_page :
166
+ while task_page and ( page_limit == - 1 or page_count < page_limit ) :
143
167
tasks += task_page
144
168
page_count += 1
145
169
task_page = self ._get_tasks (team_id , page = page_count , ** kwargs )
146
170
return tasks
147
171
148
172
def _create_task (
149
173
self ,
150
- list_id ,
151
- name , # string
152
- content , # string
153
- status , # string
154
- assignees = None , # array
155
- priority = None , # integer
156
- due_date = None , # integer posix time, or python datetime
157
- ):
174
+ list_id : str ,
175
+ name : str , # string
176
+ content : str , # string
177
+ status : str , # string
178
+ assignees : list = None , # array
179
+ priority : int = None , # integer
180
+ due_date : Union [ int , datetime ] = None , # integer posix time, or python datetime
181
+ ) -> Any :
158
182
"""creates a task in the specified list"""
159
- data = {"name" : name , "content" : content , "status" : status }
183
+ data = {
184
+ "name" : name ,
185
+ "content" : content ,
186
+ "status" : status ,
187
+ } # type: Dict[str, Any]
160
188
if assignees :
161
189
data ["assignees" ] = assignees
162
190
if priority :
@@ -166,3 +194,8 @@ def _create_task(
166
194
due_date if isinstance (due_date , int ) else datetime_to_ts (due_date )
167
195
)
168
196
return self .post ("list/{}/task" .format (list_id ), data = data )
197
+
198
+
199
+ def test_client () -> ClickUp :
200
+ """returns a test client"""
201
+ return ClickUp (TEST_TOKEN , api_url = TEST_API_URL , debug = True )
0 commit comments