11from functools import partial
2+ from typing import Any , Dict , Optional , Tuple , Type , Union
23
34import httpx
45
1011 Group ,
1112 Project ,
1213 ProjectUser ,
14+ ReportTimeEntry ,
1315 Tag ,
1416 Task ,
1517 TimeEntry ,
1618 User ,
1719 Workspace ,
1820 WorkspaceUser ,
19- ReportTimeEntry ,
2021)
2122from .exceptions import MethodNotAllowed , NotSupported
22- from .response import ReportTimeEntriesList
23+ from .response import ListResponse , ReportTimeEntriesList
24+ from .auth import BasicAuth , TokenAuth
2325
2426
2527class BaseRepository (Api ):
2628 LIST_URL = ""
27- DETAIL_URL = None
28- ENTITY_CLASS = BaseEntity
29- ADDITIONAL_METHODS = {}
30- EXCLUDED_METHODS = ()
31- ADDITIONAL_PARAMS = {}
32- DATA_CONTAINER = {}
33- LIST_RESPONSE = None
34-
35- def __init__ (self , base_url = None , auth = None ):
29+ DETAIL_URL : Optional [str ] = None
30+ ENTITY_CLASS : Type [BaseEntity ] = BaseEntity
31+ ADDITIONAL_METHODS : Dict [str , Dict [str , Any ]] = {}
32+ EXCLUDED_METHODS : Optional [Tuple [str , ...]] = None
33+ ADDITIONAL_PARAMS : Dict [str , Dict [str , Any ]] = {}
34+ DATA_CONTAINER : Dict [str , Optional [str ]] = {}
35+ LIST_RESPONSE : Optional [Type [ListResponse ]] = None
36+
37+ def __init__ (
38+ self ,
39+ base_url : Optional [str ] = None ,
40+ auth : Optional [Union [BasicAuth , TokenAuth ]] = None ,
41+ ) -> None :
3642 super ().__init__ (base_url = base_url , auth = auth )
3743 if not self .DETAIL_URL :
3844 self .DETAIL_URL = self .LIST_URL + "/{id}"
3945
40- def __getattr__ (self , method : str ):
41- if method in self .EXCLUDED_METHODS :
46+ def __getattr__ (self , attr : str ) -> Any :
47+ if self . EXCLUDED_METHODS and attr in self .EXCLUDED_METHODS :
4248 raise MethodNotAllowed
4349 try :
44- method = super ().__getattr__ (method )
50+ method = super ().__getattr__ (attr )
4551 except AttributeError :
46- if method in self .ADDITIONAL_METHODS .keys ():
52+ if attr in self .ADDITIONAL_METHODS .keys ():
4753 method = partial (
48- self .additionat_method , ** self .ADDITIONAL_METHODS [method ]
54+ self .additionat_method , ** self .ADDITIONAL_METHODS [attr ]
4955 )
5056 else :
51- raise AttributeError (f"No such method ({ method } )!" )
57+ raise AttributeError (f"No such method ({ attr } )!" )
5258 return method
5359
5460 def additionat_method (
5561 self ,
5662 url : str ,
57- _id : int = None ,
58- additional_id : int = None ,
59- entity : object = None ,
63+ _id : Optional [ int ] = None ,
64+ additional_id : Optional [ int ] = None ,
65+ entity : Any = None ,
6066 detail : bool = False ,
6167 single_item : bool = False ,
62- data_key : str = None ,
63- params : dict = None ,
64- data : dict = None ,
65- files : dict = None ,
66- ) -> httpx . Response :
68+ data_key : Optional [ str ] = None ,
69+ params : Optional [ Dict [ str , Any ]] = None ,
70+ data : Optional [ Dict [ str , Any ]] = None ,
71+ files : Optional [ Dict [ str , Any ]] = None ,
72+ ) -> Any :
6773 """
6874 Call additional method with specified url and params
6975 """
7076
7177 if detail :
78+ if not self .DETAIL_URL :
79+ raise AttributeError ("Not defined DETAIL_URL" )
7280 _url = (self .DETAIL_URL + "/" + url + "/{additional_id}" ).format (
7381 id = _id , additional_id = additional_id
7482 )
7583 return self ._retrieve (
7684 _url , entity , headers = self .HEADERS , params = params
7785 )
7886 elif _id :
87+ if not self .DETAIL_URL :
88+ raise AttributeError ("Not defined DETAIL_URL" )
7989 _url = (self .DETAIL_URL + "/" + url ).format (id = _id )
8090 return self ._list (_url , entity , headers = self .HEADERS , param = params )
8191 elif single_item :
@@ -90,7 +100,13 @@ def additionat_method(
90100 else :
91101 raise NotSupported
92102
93- def _retrieve (self , _url , entity_class , data_key : str = "data" , ** kwargs ):
103+ def _retrieve (
104+ self ,
105+ _url : Union [str , httpx .URL ],
106+ entity_class : Any ,
107+ data_key : Optional [str ] = "data" ,
108+ ** kwargs : Any ,
109+ ) -> Any :
94110 params = kwargs
95111 params .update (self .ADDITIONAL_PARAMS .get ("retrieve" , {}))
96112
@@ -102,11 +118,19 @@ def _retrieve(self, _url, entity_class, data_key: str = "data", **kwargs):
102118 if data :
103119 return entity_class (** data )
104120
105- def retrieve (self , id : int = None , ** kwargs ):
121+ def retrieve (self , id : Optional [int ] = None ) -> Any :
122+ if not self .DETAIL_URL :
123+ raise AttributeError ("Not defined DETAIL_URL" )
106124 full_url = self .BASE_URL .join (self .DETAIL_URL .format (id = id ))
107125 return self ._retrieve (full_url , self .ENTITY_CLASS )
108126
109- def _list (self , _url , entity_class , data_key : str = None , ** kwargs ):
127+ def _list (
128+ self ,
129+ _url : Union [str , httpx .URL ],
130+ entity_class : Any ,
131+ data_key : Optional [str ] = None ,
132+ ** kwargs : Any ,
133+ ) -> Any :
110134 params = kwargs
111135 params .update (self .ADDITIONAL_PARAMS .get ("list" , {}))
112136
@@ -123,29 +147,33 @@ def _list(self, _url, entity_class, data_key: str = None, **kwargs):
123147 value = self .LIST_RESPONSE (value , response_body )
124148 return value
125149
126- def list (self , ** kwargs ) :
127- if "list" in self .EXCLUDED_METHODS :
150+ def list (self , ** kwargs : Any ) -> Any :
151+ if self . EXCLUDED_METHODS and "list" in self .EXCLUDED_METHODS :
128152 raise MethodNotAllowed
129153 full_url = self .BASE_URL .join (self .LIST_URL )
130154 return self ._list (full_url , self .ENTITY_CLASS , ** kwargs )
131155
132- def create (self , entity : ENTITY_CLASS , ** kwargs ) :
133- if "create" in self .EXCLUDED_METHODS :
156+ def create (self , entity : Any , ** kwargs : Any ) -> Any :
157+ if self . EXCLUDED_METHODS and "create" in self .EXCLUDED_METHODS :
134158 raise MethodNotAllowed
135159 full_url = self .BASE_URL .join (self .LIST_URL )
136160 response = self .post (full_url , data = entity .dict (), ** kwargs )
137161 return self .ENTITY_CLASS (** response .json ())
138162
139- def update (self , entity : ENTITY_CLASS , ** kwargs ) :
140- if "update" in self .EXCLUDED_METHODS :
163+ def update (self , entity : Any , ** kwargs : Any ) -> Any :
164+ if self . EXCLUDED_METHODS and "update" in self .EXCLUDED_METHODS :
141165 raise MethodNotAllowed
166+ if not self .DETAIL_URL :
167+ raise AttributeError ("Not defined DETAIL_URL" )
142168 full_url = self .BASE_URL .join (self .DETAIL_URL .format (id = entity .id ))
143169 response = self .put (full_url , data = entity .dict (), ** kwargs )
144170 return self .ENTITY_CLASS (** response .json ())
145171
146- def partial_update (self , entity : ENTITY_CLASS , ** kwargs ) :
147- if "partial_update" in self .EXCLUDED_METHODS :
172+ def partial_update (self , entity : Any , ** kwargs : Any ) -> Any :
173+ if self . EXCLUDED_METHODS and "partial_update" in self .EXCLUDED_METHODS :
148174 raise MethodNotAllowed
175+ if not self .DETAIL_URL :
176+ raise AttributeError ("Not defined DETAIL_URL" )
149177 full_url = self .BASE_URL .join (self .DETAIL_URL .format (id = entity .id ))
150178 response = self .patch (full_url , data = entity .dict (), ** kwargs )
151179 return self .ENTITY_CLASS (** response .json ())
0 commit comments