1515# You should have received a copy of the GNU Lesser General Public License
1616# along with this program. If not, see <http://www.gnu.org/licenses/>.
1717
18+ import gitlab
1819from gitlab import base
1920
2021
@@ -70,7 +71,10 @@ def list(self, **kwargs):
7071 list(RESTObjectList).
7172 """
7273
73- obj = self .gitlab .http_list (self .path , ** kwargs )
74+ # Allow to overwrite the path, handy for custom listings
75+ path = kwargs .pop ('path' , self .path )
76+
77+ obj = self .gitlab .http_list (path , ** kwargs )
7478 if isinstance (obj , list ):
7579 return [self ._obj_cls (self , item ) for item in obj ]
7680 else :
@@ -102,7 +106,7 @@ class RetrieveMixin(ListMixin, GetMixin):
102106
103107
104108class CreateMixin (object ):
105- def _check_missing_attrs (self , data ):
109+ def _check_missing_create_attrs (self , data ):
106110 required , optional = self .get_create_attrs ()
107111 missing = []
108112 for attr in required :
@@ -119,13 +123,10 @@ def get_create_attrs(self):
119123 tuple: 2 items: list of required arguments and list of optional
120124 arguments for creation (in that order)
121125 """
122- if hasattr (self , '_create_attrs' ):
123- return (self ._create_attrs ['required' ],
124- self ._create_attrs ['optional' ])
125- return (tuple (), tuple ())
126+ return getattr (self , '_create_attrs' , (tuple (), tuple ()))
126127
127128 def create (self , data , ** kwargs ):
128- """Created a new object.
129+ """Creates a new object.
129130
130131 Args:
131132 data (dict): parameters to send to the server to create the
@@ -136,16 +137,17 @@ def create(self, data, **kwargs):
136137 RESTObject: a new instance of the manage object class build with
137138 the data sent by the server
138139 """
139- self ._check_missing_attrs (data )
140+ self ._check_missing_create_attrs (data )
140141 if hasattr (self , '_sanitize_data' ):
141142 data = self ._sanitize_data (data , 'create' )
142- server_data = self .gitlab .http_post (self .path , post_data = data ,
143- ** kwargs )
143+ # Handle specific URL for creation
144+ path = kwargs .get ('path' , self .path )
145+ server_data = self .gitlab .http_post (path , post_data = data , ** kwargs )
144146 return self ._obj_cls (self , server_data )
145147
146148
147149class UpdateMixin (object ):
148- def _check_missing_attrs (self , data ):
150+ def _check_missing_update_attrs (self , data ):
149151 required , optional = self .get_update_attrs ()
150152 missing = []
151153 for attr in required :
@@ -162,10 +164,7 @@ def get_update_attrs(self):
162164 tuple: 2 items: list of required arguments and list of optional
163165 arguments for update (in that order)
164166 """
165- if hasattr (self , '_update_attrs' ):
166- return (self ._update_attrs ['required' ],
167- self ._update_attrs ['optional' ])
168- return (tuple (), tuple ())
167+ return getattr (self , '_update_attrs' , (tuple (), tuple ()))
169168
170169 def update (self , id = None , new_data = {}, ** kwargs ):
171170 """Update an object on the server.
@@ -184,9 +183,11 @@ def update(self, id=None, new_data={}, **kwargs):
184183 else :
185184 path = '%s/%s' % (self .path , id )
186185
187- self ._check_missing_attrs (new_data )
186+ self ._check_missing_update_attrs (new_data )
188187 if hasattr (self , '_sanitize_data' ):
189188 data = self ._sanitize_data (new_data , 'update' )
189+ else :
190+ data = new_data
190191 server_data = self .gitlab .http_put (path , post_data = data , ** kwargs )
191192 return server_data
192193
@@ -205,3 +206,145 @@ def delete(self, id, **kwargs):
205206
206207class CRUDMixin (GetMixin , ListMixin , CreateMixin , UpdateMixin , DeleteMixin ):
207208 pass
209+
210+
211+ class NoUpdateMixin (GetMixin , ListMixin , CreateMixin , DeleteMixin ):
212+ pass
213+
214+
215+ class SaveMixin (object ):
216+ """Mixin for RESTObject's that can be updated."""
217+ def _get_updated_data (self ):
218+ updated_data = {}
219+ required , optional = self .manager .get_update_attrs ()
220+ for attr in required :
221+ # Get everything required, no matter if it's been updated
222+ updated_data [attr ] = getattr (self , attr )
223+ # Add the updated attributes
224+ updated_data .update (self ._updated_attrs )
225+
226+ return updated_data
227+
228+ def save (self , ** kwargs ):
229+ """Saves the changes made to the object to the server.
230+
231+ Args:
232+ **kwargs: Extra option to send to the server (e.g. sudo)
233+
234+ The object is updated to match what the server returns.
235+ """
236+ updated_data = self ._get_updated_data ()
237+
238+ # call the manager
239+ obj_id = self .get_id ()
240+ server_data = self .manager .update (obj_id , updated_data , ** kwargs )
241+ self ._update_attrs (server_data )
242+
243+
244+ class AccessRequestMixin (object ):
245+ def approve (self , access_level = gitlab .DEVELOPER_ACCESS , ** kwargs ):
246+ """Approve an access request.
247+
248+ Attrs:
249+ access_level (int): The access level for the user.
250+
251+ Raises:
252+ GitlabConnectionError: If the server cannot be reached.
253+ GitlabUpdateError: If the server fails to perform the request.
254+ """
255+
256+ path = '%s/%s/approve' % (self .manager .path , self .id )
257+ data = {'access_level' : access_level }
258+ server_data = self .manager .gitlab .http_put (url , post_data = data ,
259+ ** kwargs )
260+ self ._update_attrs (server_data )
261+
262+
263+ class SubscribableMixin (object ):
264+ def subscribe (self , ** kwarg ):
265+ """Subscribe to the object notifications.
266+
267+ raises:
268+ gitlabconnectionerror: if the server cannot be reached.
269+ gitlabsubscribeerror: if the subscription cannot be done
270+ """
271+ path = '%s/%s/subscribe' % (self .manager .path , self .get_id ())
272+ server_data = self .manager .gitlab .http_post (path , ** kwargs )
273+ self ._update_attrs (server_data )
274+
275+ def unsubscribe (self , ** kwargs ):
276+ """Unsubscribe from the object notifications.
277+
278+ raises:
279+ gitlabconnectionerror: if the server cannot be reached.
280+ gitlabunsubscribeerror: if the unsubscription cannot be done
281+ """
282+ path = '%s/%s/unsubscribe' % (self .manager .path , self .get_id ())
283+ server_data = self .manager .gitlab .http_post (path , ** kwargs )
284+ self ._update_attrs (server_data )
285+
286+
287+ class TodoMixin (object ):
288+ def todo (self , ** kwargs ):
289+ """Create a todo associated to the object.
290+
291+ Raises:
292+ GitlabConnectionError: If the server cannot be reached.
293+ """
294+ path = '%s/%s/todo' % (self .manager .path , self .get_id ())
295+ self .manager .gitlab .http_post (path , ** kwargs )
296+
297+
298+ class TimeTrackingMixin (object ):
299+ def time_stats (self , ** kwargs ):
300+ """Get time stats for the object.
301+
302+ Raises:
303+ GitlabConnectionError: If the server cannot be reached.
304+ """
305+ path = '%s/%s/time_stats' % (self .manager .path , self .get_id ())
306+ return self .manager .gitlab .http_get (path , ** kwargs )
307+
308+ def time_estimate (self , duration , ** kwargs ):
309+ """Set an estimated time of work for the object.
310+
311+ Args:
312+ duration (str): duration in human format (e.g. 3h30)
313+
314+ Raises:
315+ GitlabConnectionError: If the server cannot be reached.
316+ """
317+ path = '%s/%s/time_estimate' % (self .manager .path , self .get_id ())
318+ data = {'duration' : duration }
319+ return self .manager .gitlab .http_post (path , post_data = data , ** kwargs )
320+
321+ def reset_time_estimate (self , ** kwargs ):
322+ """Resets estimated time for the object to 0 seconds.
323+
324+ Raises:
325+ GitlabConnectionError: If the server cannot be reached.
326+ """
327+ path = '%s/%s/rest_time_estimate' % (self .manager .path , self .get_id ())
328+ return self .manager .gitlab .http_post (path , ** kwargs )
329+
330+ def add_spent_time (self , duration , ** kwargs ):
331+ """Add time spent working on the object.
332+
333+ Args:
334+ duration (str): duration in human format (e.g. 3h30)
335+
336+ Raises:
337+ GitlabConnectionError: If the server cannot be reached.
338+ """
339+ path = '%s/%s/add_spent_time' % (self .manager .path , self .get_id ())
340+ data = {'duration' : duration }
341+ return self .manager .gitlab .http_post (path , post_data = data , ** kwargs )
342+
343+ def reset_spent_time (self , ** kwargs ):
344+ """Resets the time spent working on the object.
345+
346+ Raises:
347+ GitlabConnectionError: If the server cannot be reached.
348+ """
349+ path = '%s/%s/reset_spent_time' % (self .manager .path , self .get_id ())
350+ return self .manager .gitlab .http_post (path , ** kwargs )
0 commit comments