Skip to content

Commit 1d7ebea

Browse files
author
Gauvain Pocentek
committed
Support deletion without getting the object first
Use this feature in the CLI to avoid an extra API call to the server.
1 parent e5821e6 commit 1d7ebea

File tree

4 files changed

+50
-7
lines changed

4 files changed

+50
-7
lines changed

gitlab/__init__.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from __future__ import print_function
2020
from __future__ import division
2121
from __future__ import absolute_import
22+
import inspect
2223
import itertools
2324
import json
2425
import warnings
@@ -419,11 +420,14 @@ def get(self, obj_class, id=None, **kwargs):
419420
raise_error_from_response(r, GitlabGetError)
420421
return r.json()
421422

422-
def delete(self, obj, **kwargs):
423+
def delete(self, obj, id=None, **kwargs):
423424
"""Delete an object on the GitLab server.
424425
425426
Args:
426-
obj (object): The object to delete.
427+
obj (object or id): The object, or the class of the object to
428+
delete. If it is the class, the id of the object must be
429+
specified as the `id` arguments.
430+
id: ID of the object to remove. Required if `obj` is a class.
427431
**kwargs: Additional arguments to send to GitLab.
428432
429433
Returns:
@@ -433,7 +437,13 @@ def delete(self, obj, **kwargs):
433437
GitlabConnectionError: If the server cannot be reached.
434438
GitlabDeleteError: If the server fails to perform the request.
435439
"""
436-
params = obj.__dict__.copy()
440+
if inspect.isclass(obj):
441+
if not issubclass(obj, GitlabObject):
442+
raise GitlabError("Invalid class: %s" % obj)
443+
params = {}
444+
params[obj.idAttr] = id
445+
else:
446+
params = obj.__dict__.copy()
437447
params.update(kwargs)
438448
missing = []
439449
for k in itertools.chain(obj.requiredUrlAttrs,
@@ -444,7 +454,7 @@ def delete(self, obj, **kwargs):
444454
raise GitlabDeleteError('Missing attribute(s): %s' %
445455
", ".join(missing))
446456

447-
obj_id = getattr(obj, obj.idAttr)
457+
obj_id = params[obj.idAttr]
448458
url = self._construct_url(id_=obj_id, obj=obj, parameters=params)
449459
headers = self._create_headers()
450460

gitlab/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,9 @@ def do_delete(cls, gl, what, args):
188188
if not cls.canDelete:
189189
_die("%s objects can't be deleted" % what)
190190

191-
o = do_get(cls, gl, what, args)
191+
id = args.pop(cls.idAttr)
192192
try:
193-
o.delete()
193+
gl.delete(cls, id, **args)
194194
except Exception as e:
195195
_die("Impossible to destroy object (%s)" % str(e))
196196

gitlab/objects.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,21 @@ def create(self, data, **kwargs):
134134
raise NotImplementedError
135135
return self.obj_cls.create(self.gitlab, data, **kwargs)
136136

137+
def delete(self, id, **kwargs):
138+
"""Delete a GitLab object.
139+
140+
Args:
141+
id: ID of the object to delete.
142+
143+
Raises:
144+
NotImplementedError: If objects cannot be deleted.
145+
GitlabDeleteError: If the server fails to perform the request.
146+
"""
147+
self._set_parent_args(**kwargs)
148+
if not self.obj_cls.canDelete:
149+
raise NotImplementedError
150+
self.gitlab.delete(self.obj_cls, id, **kwargs)
151+
137152
def _custom_list(self, url, cls, **kwargs):
138153
r = self.gitlab._raw_get(url, **kwargs)
139154
raise_error_from_response(r, GitlabListError)

gitlab/tests/test_gitlab.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ def resp_cont(url, request):
338338
self.assertRaises(GitlabGetError, self.gl.get,
339339
Project, 1)
340340

341-
def test_delete(self):
341+
def test_delete_from_object(self):
342342
@urlmatch(scheme="http", netloc="localhost", path="/api/v3/groups/1",
343343
method="delete")
344344
def resp_delete_group(url, request):
@@ -351,6 +351,24 @@ def resp_delete_group(url, request):
351351
data = self.gl.delete(obj)
352352
self.assertIs(data, True)
353353

354+
def test_delete_from_invalid_class(self):
355+
class InvalidClass(object):
356+
pass
357+
358+
self.assertRaises(GitlabError, self.gl.delete, InvalidClass, 1)
359+
360+
def test_delete_from_class(self):
361+
@urlmatch(scheme="http", netloc="localhost", path="/api/v3/groups/1",
362+
method="delete")
363+
def resp_delete_group(url, request):
364+
headers = {'content-type': 'application/json'}
365+
content = ''.encode("utf-8")
366+
return response(200, content, headers, None, 5, request)
367+
368+
with HTTMock(resp_delete_group):
369+
data = self.gl.delete(Group, 1)
370+
self.assertIs(data, True)
371+
354372
def test_delete_unknown_path(self):
355373
obj = Project(self.gl, data={"name": "testname", "id": 1})
356374
obj._from_api = True

0 commit comments

Comments
 (0)