11import logging
22import time
3+ import requests
4+ import typing
35
4- from functools import partial
5- try : # Python 3
6- from urllib .parse import urljoin
7- except ImportError : # Python 2
8- from urlparse import urljoin
6+ #import helpscout
7+ if typing .TYPE_CHECKING :
8+ from collections .abc import Generator
99
10- import requests
10+ from functools import partial
11+ from urllib .parse import urljoin
1112
1213from helpscout .exceptions import (HelpScoutException ,
1314 HelpScoutAuthenticationException ,
2223
2324class HelpScout :
2425
25- def __init__ (self , app_id , app_secret ,
26- base_url = 'https://api.helpscout.net/v2/' ,
27- sleep_on_rate_limit_exceeded = True ,
28- rate_limit_sleep = 10 ):
26+ def __init__ (self , app_id : str , app_secret : str ,
27+ base_url : str = 'https://api.helpscout.net/v2/' ,
28+ sleep_on_rate_limit_exceeded : bool = True ,
29+ rate_limit_sleep : int = 10 ):
2930 """Help Scout API v2 client wrapper.
3031
3132 The app credentials are created on the My App section in your profile.
@@ -40,7 +41,7 @@ def __init__(self, app_id, app_secret,
4041 The application secret.
4142 base_url: str
4243 The API's base url.
43- sleep_on_rate_limit_exceeded: Boolean
44+ sleep_on_rate_limit_exceeded: bool
4445 True to sleep and retry on rate limits exceeded.
4546 Otherwise raises an HelpScoutRateLimitExceededException exception.
4647 rate_limit_sleep: int
@@ -54,7 +55,7 @@ def __init__(self, app_id, app_secret,
5455 self .rate_limit_sleep = rate_limit_sleep
5556 self .access_token = None
5657
57- def __getattr__ (self , endpoint ) :
58+ def __getattr__ (self , endpoint : str ) -> 'HelpScoutEndpointRequester' :
5859 """Returns a request to hit the API in a nicer way. E.g.:
5960 > client = HelpScout(app_id='asdasd', app_secret='1021')
6061 > client.conversations.get()
@@ -76,19 +77,18 @@ def __getattr__(self, endpoint):
7677 """
7778 return HelpScoutEndpointRequester (self , endpoint , False )
7879
79- def get_objects (self , endpoint , resource_id = None , params = None ,
80- specific_resource = False ):
80+ def get_objects (self , endpoint :str , resource_id :int | str | None = None , params :dict | str | None = None , specific_resource :bool = False ) -> HelpScoutObject | list [HelpScoutObject ]:
8181 """Returns the objects from the endpoint filtering by the parameters.
8282
8383 Parameters
8484 ----------
8585 endpoint: str
8686 One of the endpoints in the API. E.g.: conversations, mailboxes.
87- resource_id: int or str or None
87+ resource_id: int | str | None
8888 The id of the resource in the endpoint to query.
8989 E.g.: in "GET /v2/conversations/123 HTTP/1.1" the id would be 123.
9090 If None is provided, nothing will be done
91- params: dict or str or None
91+ params: dict | str | None
9292 Dictionary with the parameters to send to the url.
9393 Or the parameters already un url format.
9494 specific_resource: bool
@@ -98,17 +98,16 @@ def get_objects(self, endpoint, resource_id=None, params=None,
9898
9999 Returns
100100 -------
101- [HelpScoutObject]
101+ HelpScoutObject | list [HelpScoutObject]
102102 A list of objects returned by the api.
103103 """
104104 cls = HelpScoutObject .cls (endpoint , endpoint )
105- results = cls .from_results (
106- self .hit_ (endpoint , 'get' , resource_id , params = params ))
105+ results :list [HelpScoutObject ] = cls .from_results ( self .hit_ (endpoint , 'get' , resource_id , params = params ) )
107106 if resource_id is not None or specific_resource :
108107 return results [0 ]
109108 return results
110109
111- def hit (self , endpoint , method , resource_id = None , data = None , params = None ):
110+ def hit (self , endpoint : str , method : str , resource_id : int | str | None = None , data : dict | None = None , params : dict | str | None = None ) -> list [ dict | None ] :
112111 """Hits the api and returns all the data.
113112 If several calls are needed due to pagination, control won't be
114113 returned to the caller until all is retrieved.
@@ -120,26 +119,26 @@ def hit(self, endpoint, method, resource_id=None, data=None, params=None):
120119 method: str
121120 The http method to hit the endpoint with.
122121 One of {'get', 'post', 'put', 'patch', 'delete', 'head', 'options'}
123- resource_id: int or str or None
122+ resource_id: int | str | None
124123 The id of the resource in the endpoint to query.
125124 E.g.: in "GET /v2/conversations/123 HTTP/1.1" the id would be 123.
126125 If None is provided, nothing will be done
127- data : dict or None
126+ dict : dict | None
128127 A dictionary with the data to send to the API as json.
129- params: dict or str or None
128+ params: dict | str | None
130129 Dictionary with the parameters to send to the url.
131130 Or the parameters already un url format.
132131
133132 Returns
134133 -------
135- [dict] or [None]
136- dict : when several objects are received from the API, a list of
134+ list [dict] | list [None]
135+ list : when several objects are received from the API, a list of
137136 dictionaries with HelpScout's _embedded data will be returned
138137 None if http 201 created or 204 no content are received.
139138 """
140139 return list (self .hit_ (endpoint , method , resource_id , data , params ))
141140
142- def hit_ (self , endpoint , method , resource_id = None , data = None , params = None ):
141+ def hit_ (self , endpoint : str , method : str , resource_id : int | str | None = None , data : dict | None = None , params : dict | str | None = None ) -> Generator [ dict | None , None , None ] :
143142 """Hits the api and yields the data.
144143
145144 Parameters
@@ -149,19 +148,19 @@ def hit_(self, endpoint, method, resource_id=None, data=None, params=None):
149148 method: str
150149 The http method to hit the endpoint with.
151150 One of {'get', 'post', 'put', 'patch', 'delete', 'head', 'options'}
152- resource_id: int or str or None
151+ resource_id: int | str | None
153152 The id of the resource in the endpoint to query.
154153 E.g.: in "GET /v2/conversations/123 HTTP/1.1" the id would be 123.
155154 If None is provided, nothing will be done
156- data: dict or None
155+ data: dict | None
157156 A dictionary with the data to send to the API as json.
158- params: dict or str or None
157+ params: dict | str | None
159158 Dictionary with the parameters to send to the url.
160159 Or the parameters already un url format.
161160
162161 Yields
163162 ------
164- dict or None
163+ dict | None
165164 Dictionary with HelpScout's _embedded data.
166165 None if http 201 created or 204 no content are received.
167166 """
@@ -197,7 +196,7 @@ def hit_(self, endpoint, method, resource_id=None, data=None, params=None):
197196 else :
198197 raise HelpScoutException (r .text )
199198
200- def _results_with_pagination (self , response , method ) :
199+ def _results_with_pagination (self , response : dict , method : str ) -> Generator [ dict , None , None ] :
201200 """Requests and yields pagination results.
202201
203202 Parameters
@@ -243,8 +242,7 @@ def _results_with_pagination(self, response, method):
243242 raise HelpScoutException (r .text )
244243
245244 def _authenticate (self ):
246- """Authenticates with the API and gets a token for subsequent requests.
247- """
245+ """Authenticates with the API and gets a token for subsequent requests."""
248246 url = urljoin (self .base_url , 'oauth2/token' )
249247 data = {
250248 'grant_type' : 'client_credentials' ,
@@ -287,7 +285,7 @@ def __eq__(self, other):
287285 self .sleep_on_rate_limit_exceeded ==
288286 other .sleep_on_rate_limit_exceeded )
289287
290- def __repr__ (self ):
288+ def __repr__ (self ) -> str :
291289 """Returns the object as a string."""
292290 name = self .__class__ .__name__
293291 attrs = (
@@ -307,12 +305,12 @@ def __repr__(self):
307305
308306class HelpScoutEndpointRequester :
309307
310- def __init__ (self , client , endpoint , specific_resource ):
308+ def __init__ (self , client : HelpScout , endpoint : str , specific_resource : bool ):
311309 """Client wrapper to perform requester.get/post/put/patch/delete.
312310
313311 Parameters
314312 ----------
315- client: HelpScoutClient
313+ client: HelpScout
316314 A help scout client instance to query the API.
317315 endpoint: str
318316 One of the endpoints in the API. E.g.: conversations, mailboxes.
@@ -324,7 +322,7 @@ def __init__(self, client, endpoint, specific_resource):
324322 self .endpoint = endpoint
325323 self .specific_resource = specific_resource
326324
327- def __getattr__ (self , method ) :
325+ def __getattr__ (self , method : str ) -> 'partial | HelpScoutEndpointRequester' :
328326 """Catches http methods like get, post, patch, put and delete.
329327 Returns a subrequester when methods not named after http methods are
330328 requested, as this are considered attributes of the main object, like
@@ -359,7 +357,7 @@ def __getattr__(self, method):
359357 False ,
360358 )
361359
362- def __getitem__ (self , resource_id ) :
360+ def __getitem__ (self , resource_id : int | str ) -> 'HelpScoutEndpointRequester' :
363361 """Returns a second endpoint requester extending the endpoint to a
364362 specific resource_id or resource_name.
365363
@@ -368,7 +366,7 @@ def __getitem__(self, resource_id):
368366
369367 Parameters
370368 ----------
371- resource_id: int or str
369+ resource_id: int | str
372370 The resource id or attribute available in the API through a
373371 specific call.
374372
@@ -408,7 +406,7 @@ def __eq__(self, other):
408406 self .endpoint == other .endpoint and
409407 self .client == other .client )
410408
411- def __repr__ (self ):
409+ def __repr__ (self ) -> str :
412410 """Returns the object as a string."""
413411 name = self .__class__ .__name__
414412 return '%s(app_id="%s", endpoint="%s")' % (
0 commit comments