Skip to content

Commit 97c8619

Browse files
author
Gauvain Pocentek
committed
Add support for the search API
Fixes #470
1 parent b5f9616 commit 97c8619

File tree

5 files changed

+119
-0
lines changed

5 files changed

+119
-0
lines changed

docs/api-objects.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ API examples
2828
gl_objects/pagesdomains
2929
gl_objects/projects
3030
gl_objects/runners
31+
gl_objects/search
3132
gl_objects/settings
3233
gl_objects/snippets
3334
gl_objects/system_hooks

docs/gl_objects/search.rst

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
##########
2+
Search API
3+
##########
4+
5+
You can search for resources at the top level, in a project or in a group.
6+
Searches are based on a scope (issues, merge requests, and so on) and a search
7+
string.
8+
9+
Reference
10+
---------
11+
12+
* v4 API:
13+
14+
+ :attr:`gitlab.Gitlab.search`
15+
+ :attr:`gitlab.v4.objects.Group.search`
16+
+ :attr:`gitlab.v4.objects.Project.search`
17+
18+
* GitLab API: https://docs.gitlab.com/ce/api/search.html
19+
20+
Examples
21+
--------
22+
23+
Search for issues matching a specific string::
24+
25+
# global search
26+
gl.search('issues', 'regression')
27+
28+
# group search
29+
group = gl.groups.get('mygroup')
30+
group.search('issues', 'regression')
31+
32+
# project search
33+
project = gl.projects.get('myproject')
34+
project.search('issues', 'regression')
35+
36+
The ``search()`` methods implement the pagination support::
37+
38+
# get lists of 10 items, and start at page 2
39+
gl.search('issues', search_str, page=2, per_page=10)
40+
41+
# get a generator that will automatically make required API calls for
42+
# pagination
43+
for item in gl.search('issues', search_str, as_list=False):
44+
do_something(item)
45+
46+
The search API doesn't return objects, but dicts. If you need to act on
47+
objects, you need to create them explicitly::
48+
49+
for item in gl.search('issues', search_str, as_list=False):
50+
issue_project = gl.projects.get(item['project_id'], lazy=True)
51+
issue = issue_project.issues.get(item['iid'])
52+
issue.state = 'closed'
53+
issue.save()

gitlab/__init__.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,25 @@ def http_delete(self, path, **kwargs):
555555
"""
556556
return self.http_request('delete', path, **kwargs)
557557

558+
@on_http_error(GitlabSearchError)
559+
def search(self, scope, search, **kwargs):
560+
"""Search GitLab resources matching the provided string.'
561+
562+
Args:
563+
scope (str): Scope of the search
564+
search (str): Search string
565+
**kwargs: Extra options to send to the server (e.g. sudo)
566+
567+
Raises:
568+
GitlabAuthenticationError: If authentication is not correct
569+
GitlabSearchError: If the server failed to perform the request
570+
571+
Returns:
572+
GitlabList: A list of dicts describing the resources found.
573+
"""
574+
data = {'scope': scope, 'search': search}
575+
return self.http_list('/search', query_data=data, **kwargs)
576+
558577

559578
class GitlabList(object):
560579
"""Generator representing a list of remote objects.

gitlab/exceptions.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,10 @@ class GitlabOwnershipError(GitlabOperationError):
197197
pass
198198

199199

200+
class GitlabSearchError(GitlabOperationError):
201+
pass
202+
203+
200204
def on_http_error(error):
201205
"""Manage GitlabHttpError exceptions.
202206

gitlab/v4/objects.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,27 @@ def transfer_project(self, to_project_id, **kwargs):
713713
path = '/groups/%d/projects/%d' % (self.id, to_project_id)
714714
self.manager.gitlab.http_post(path, **kwargs)
715715

716+
@cli.register_custom_action('Group', ('scope', 'search'))
717+
@exc.on_http_error(exc.GitlabSearchError)
718+
def search(self, scope, search, **kwargs):
719+
"""Search the group resources matching the provided string.'
720+
721+
Args:
722+
scope (str): Scope of the search
723+
search (str): Search string
724+
**kwargs: Extra options to send to the server (e.g. sudo)
725+
726+
Raises:
727+
GitlabAuthenticationError: If authentication is not correct
728+
GitlabSearchError: If the server failed to perform the request
729+
730+
Returns:
731+
GitlabList: A list of dicts describing the resources found.
732+
"""
733+
data = {'scope': scope, 'search': search}
734+
path = '/groups/%d/search' % self.get_id()
735+
return self.manager.gitlab.http_list(path, query_data=data, **kwargs)
736+
716737

717738
class GroupManager(CRUDMixin, RESTManager):
718739
_path = '/groups'
@@ -2867,6 +2888,27 @@ def upload(self, filename, filedata=None, filepath=None, **kwargs):
28672888
"markdown": data['markdown']
28682889
}
28692890

2891+
@cli.register_custom_action('Project', ('scope', 'search'))
2892+
@exc.on_http_error(exc.GitlabSearchError)
2893+
def search(self, scope, search, **kwargs):
2894+
"""Search the project resources matching the provided string.'
2895+
2896+
Args:
2897+
scope (str): Scope of the search
2898+
search (str): Search string
2899+
**kwargs: Extra options to send to the server (e.g. sudo)
2900+
2901+
Raises:
2902+
GitlabAuthenticationError: If authentication is not correct
2903+
GitlabSearchError: If the server failed to perform the request
2904+
2905+
Returns:
2906+
GitlabList: A list of dicts describing the resources found.
2907+
"""
2908+
data = {'scope': scope, 'search': search}
2909+
path = '/projects/%d/search' % self.get_id()
2910+
return self.manager.gitlab.http_list(path, query_data=data, **kwargs)
2911+
28702912

28712913
class ProjectManager(CRUDMixin, RESTManager):
28722914
_path = '/projects'

0 commit comments

Comments
 (0)