diff options
author | Gauvain Pocentek <gauvain@pocentek.net> | 2018-05-21 16:21:48 +0200 |
---|---|---|
committer | Gauvain Pocentek <gauvain@pocentek.net> | 2018-05-21 16:21:48 +0200 |
commit | 97c8619c5b07abc714417d6e5be2f553270b54a6 (patch) | |
tree | ff7ac748615cf0a2b18eedd9c789b8eaf0396263 | |
parent | b5f9616f21b7dcdf166033d0dba09b3dd2289849 (diff) | |
download | gitlab-97c8619c5b07abc714417d6e5be2f553270b54a6.tar.gz |
Add support for the search API
Fixes #470
-rw-r--r-- | docs/api-objects.rst | 1 | ||||
-rw-r--r-- | docs/gl_objects/search.rst | 53 | ||||
-rw-r--r-- | gitlab/__init__.py | 19 | ||||
-rw-r--r-- | gitlab/exceptions.py | 4 | ||||
-rw-r--r-- | gitlab/v4/objects.py | 42 |
5 files changed, 119 insertions, 0 deletions
diff --git a/docs/api-objects.rst b/docs/api-objects.rst index c4bc421..3c221c6 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -28,6 +28,7 @@ API examples gl_objects/pagesdomains gl_objects/projects gl_objects/runners + gl_objects/search gl_objects/settings gl_objects/snippets gl_objects/system_hooks diff --git a/docs/gl_objects/search.rst b/docs/gl_objects/search.rst new file mode 100644 index 0000000..750bbe0 --- /dev/null +++ b/docs/gl_objects/search.rst @@ -0,0 +1,53 @@ +########## +Search API +########## + +You can search for resources at the top level, in a project or in a group. +Searches are based on a scope (issues, merge requests, and so on) and a search +string. + +Reference +--------- + +* v4 API: + + + :attr:`gitlab.Gitlab.search` + + :attr:`gitlab.v4.objects.Group.search` + + :attr:`gitlab.v4.objects.Project.search` + +* GitLab API: https://docs.gitlab.com/ce/api/search.html + +Examples +-------- + +Search for issues matching a specific string:: + + # global search + gl.search('issues', 'regression') + + # group search + group = gl.groups.get('mygroup') + group.search('issues', 'regression') + + # project search + project = gl.projects.get('myproject') + project.search('issues', 'regression') + +The ``search()`` methods implement the pagination support:: + + # get lists of 10 items, and start at page 2 + gl.search('issues', search_str, page=2, per_page=10) + + # get a generator that will automatically make required API calls for + # pagination + for item in gl.search('issues', search_str, as_list=False): + do_something(item) + +The search API doesn't return objects, but dicts. If you need to act on +objects, you need to create them explicitly:: + + for item in gl.search('issues', search_str, as_list=False): + issue_project = gl.projects.get(item['project_id'], lazy=True) + issue = issue_project.issues.get(item['iid']) + issue.state = 'closed' + issue.save() diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 3a36bf2..c0562da 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -555,6 +555,25 @@ class Gitlab(object): """ return self.http_request('delete', path, **kwargs) + @on_http_error(GitlabSearchError) + def search(self, scope, search, **kwargs): + """Search GitLab resources matching the provided string.' + + Args: + scope (str): Scope of the search + search (str): Search string + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabSearchError: If the server failed to perform the request + + Returns: + GitlabList: A list of dicts describing the resources found. + """ + data = {'scope': scope, 'search': search} + return self.http_list('/search', query_data=data, **kwargs) + class GitlabList(object): """Generator representing a list of remote objects. diff --git a/gitlab/exceptions.py b/gitlab/exceptions.py index 744890f..00d99c6 100644 --- a/gitlab/exceptions.py +++ b/gitlab/exceptions.py @@ -197,6 +197,10 @@ class GitlabOwnershipError(GitlabOperationError): pass +class GitlabSearchError(GitlabOperationError): + pass + + def on_http_error(error): """Manage GitlabHttpError exceptions. diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index ac25f1e..6f40dc8 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -713,6 +713,27 @@ class Group(SaveMixin, ObjectDeleteMixin, RESTObject): path = '/groups/%d/projects/%d' % (self.id, to_project_id) self.manager.gitlab.http_post(path, **kwargs) + @cli.register_custom_action('Group', ('scope', 'search')) + @exc.on_http_error(exc.GitlabSearchError) + def search(self, scope, search, **kwargs): + """Search the group resources matching the provided string.' + + Args: + scope (str): Scope of the search + search (str): Search string + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabSearchError: If the server failed to perform the request + + Returns: + GitlabList: A list of dicts describing the resources found. + """ + data = {'scope': scope, 'search': search} + path = '/groups/%d/search' % self.get_id() + return self.manager.gitlab.http_list(path, query_data=data, **kwargs) + class GroupManager(CRUDMixin, RESTManager): _path = '/groups' @@ -2867,6 +2888,27 @@ class Project(SaveMixin, ObjectDeleteMixin, RESTObject): "markdown": data['markdown'] } + @cli.register_custom_action('Project', ('scope', 'search')) + @exc.on_http_error(exc.GitlabSearchError) + def search(self, scope, search, **kwargs): + """Search the project resources matching the provided string.' + + Args: + scope (str): Scope of the search + search (str): Search string + **kwargs: Extra options to send to the server (e.g. sudo) + + Raises: + GitlabAuthenticationError: If authentication is not correct + GitlabSearchError: If the server failed to perform the request + + Returns: + GitlabList: A list of dicts describing the resources found. + """ + data = {'scope': scope, 'search': search} + path = '/projects/%d/search' % self.get_id() + return self.manager.gitlab.http_list(path, query_data=data, **kwargs) + class ProjectManager(CRUDMixin, RESTManager): _path = '/projects' |