From 343c131069c76fe68900d95b2a3e996e25e5c9c7 Mon Sep 17 00:00:00 2001 From: Michal Galet Date: Mon, 12 Dec 2016 10:18:24 +0100 Subject: [PATCH 01/15] Fix JIRA service editing for GitLab 8.14+ GitLab simplified the configuration for JIRA service and renamed most of the fields. To maintain backward compatibility all mandatory fields were moved to optional section. --- gitlab/objects.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/gitlab/objects.py b/gitlab/objects.py index 2560ba4d0..eaae9c6b4 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -1992,8 +1992,16 @@ class ProjectService(GitlabObject): 'server')), 'irker': (('recipients', ), ('default_irc_uri', 'server_port', 'server_host', 'colorize_messages')), - 'jira': (('new_issue_url', 'project_url', 'issues_url'), - ('api_url', 'description', 'username', 'password')), + 'jira': (tuple(), ( + # Required fields in GitLab >= 8.14 + 'url', 'project_key', + + # Required fields in GitLab < 8.14 + 'new_issue_url', 'project_url', 'issues_url', 'api_url', + 'description', + + # Optional fields + 'username', 'password')), 'pivotaltracker': (('token', ), tuple()), 'pushover': (('api_key', 'user_key', 'priority'), ('device', 'sound')), 'redmine': (('new_issue_url', 'project_url', 'issues_url'), From f7e6482f6f8e5a5893f22739ec98005846c74eec Mon Sep 17 00:00:00 2001 From: Michal Galet Date: Mon, 12 Dec 2016 10:24:54 +0100 Subject: [PATCH 02/15] Add jira_issue_transition_id to the JIRA service optional fields --- gitlab/objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab/objects.py b/gitlab/objects.py index eaae9c6b4..4d1e7b802 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -2001,7 +2001,7 @@ class ProjectService(GitlabObject): 'description', # Optional fields - 'username', 'password')), + 'username', 'password', 'jira_issue_transition_id')), 'pivotaltracker': (('token', ), tuple()), 'pushover': (('api_key', 'user_key', 'priority'), ('device', 'sound')), 'redmine': (('new_issue_url', 'project_url', 'issues_url'), From 6022dfec44c67f7f45b0c3274f5eef02e8ac93f0 Mon Sep 17 00:00:00 2001 From: Guyzmo Date: Sun, 27 Nov 2016 13:43:38 +0100 Subject: [PATCH 03/15] Added support for Snippets (new API in Gitlab 8.15) cf [Gitlab-CE MR !6373](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/6373) Signed-off-by: Guyzmo --- gitlab/__init__.py | 4 +- gitlab/objects.py | 61 +++++++++++++++++++++++++++++++ gitlab/tests/test_gitlabobject.py | 34 +++++++++++++++++ 3 files changed, 98 insertions(+), 1 deletion(-) diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 82a241441..679b023d2 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -103,6 +103,7 @@ def __init__(self, url, private_token=None, email=None, password=None, self.runners = RunnerManager(self) self.settings = ApplicationSettingsManager(self) self.sidekiq = SidekiqManager(self) + self.snippets = SnippetManager(self) self.users = UserManager(self) self.teams = TeamManager(self) self.todos = TodoManager(self) @@ -469,7 +470,8 @@ def delete(self, obj, id=None, **kwargs): params.pop(obj.idAttr) r = self._raw_delete(url, **params) - raise_error_from_response(r, GitlabDeleteError) + raise_error_from_response(r, GitlabDeleteError, + expected_code=[200, 204]) return True def create(self, obj, **kwargs): diff --git a/gitlab/objects.py b/gitlab/objects.py index 4d1e7b802..dcf5d5c2e 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -1018,6 +1018,67 @@ class LicenseManager(BaseManager): obj_cls = License +class Snippet(GitlabObject): + _url = '/snippets' + _constructorTypes = {'author': 'User'} + requiredCreateAttrs = ['title', 'file_name', 'content'] + optionalCreateAttrs = ['lifetime', 'visibility_level'] + optionalUpdateAttrs = ['title', 'file_name', 'content', 'visibility_level'] + shortPrintAttr = 'title' + + def content(self, streamed=False, action=None, chunk_size=1024, **kwargs): + """Return the raw content of a snippet. + + Args: + streamed (bool): If True the data will be processed by chunks of + `chunk_size` and each chunk is passed to `action` for + treatment. + action (callable): Callable responsible of dealing with chunk of + data. + chunk_size (int): Size of each chunk. + + Returns: + str: The snippet content + + Raises: + GitlabConnectionError: If the server cannot be reached. + GitlabGetError: If the server fails to perform the request. + """ + url = ("/snippets/%(snippet_id)s/raw" % + {'snippet_id': self.id}) + r = self.gitlab._raw_get(url, **kwargs) + raise_error_from_response(r, GitlabGetError) + return utils.response_content(r, streamed, action, chunk_size) + + +class SnippetManager(BaseManager): + obj_cls = Snippet + + def all(self, **kwargs): + """List all the snippets + + Args: + all (bool): If True, return all the items, without pagination + **kwargs: Additional arguments to send to GitLab. + + Returns: + list(gitlab.Gitlab.Snippet): The list of snippets. + """ + return self.gitlab._raw_list("/snippets/public", Snippet, **kwargs) + + def owned(self, **kwargs): + """List owned snippets. + + Args: + all (bool): If True, return all the items, without pagination + **kwargs: Additional arguments to send to GitLab. + + Returns: + list(gitlab.Gitlab.Snippet): The list of owned snippets. + """ + return self.gitlab._raw_list("/snippets", Snippet, **kwargs) + + class Namespace(GitlabObject): _url = '/namespaces' canGet = 'from_list' diff --git a/gitlab/tests/test_gitlabobject.py b/gitlab/tests/test_gitlabobject.py index cf06a2a9d..d191c0f07 100644 --- a/gitlab/tests/test_gitlabobject.py +++ b/gitlab/tests/test_gitlabobject.py @@ -455,3 +455,37 @@ def test_content(self): def test_blob_fail(self): with HTTMock(self.resp_content_fail): self.assertRaises(GitlabGetError, self.obj.content) + + +class TestSnippet(unittest.TestCase): + def setUp(self): + self.gl = Gitlab("http://localhost", private_token="private_token", + email="testuser@test.com", password="testpassword", + ssl_verify=True) + self.obj = Snippet(self.gl, data={"id": 3}) + + @urlmatch(scheme="http", netloc="localhost", + path="/api/v3/snippets/3/raw", + method="get") + def resp_content(self, url, request): + headers = {'content-type': 'application/json'} + content = 'content'.encode("utf-8") + return response(200, content, headers, None, 5, request) + + @urlmatch(scheme="http", netloc="localhost", + path="/api/v3/snippets/3/raw", + method="get") + def resp_content_fail(self, url, request): + headers = {'content-type': 'application/json'} + content = '{"message": "messagecontent" }'.encode("utf-8") + return response(400, content, headers, None, 5, request) + + def test_content(self): + with HTTMock(self.resp_content): + data = b'content' + content = self.obj.content() + self.assertEqual(content, data) + + def test_blob_fail(self): + with HTTMock(self.resp_content_fail): + self.assertRaises(GitlabGetError, self.obj.content) From d86ca59dbe1d7f852416ec227a7d241d236424cf Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 24 Dec 2016 14:34:27 +0100 Subject: [PATCH 04/15] [docs] update pagination section First page is page 1. Fixes #197 --- docs/api-usage.rst | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/api-usage.rst b/docs/api-usage.rst index b33913dca..4f8cb3717 100644 --- a/docs/api-usage.rst +++ b/docs/api-usage.rst @@ -111,7 +111,12 @@ listing methods support the ``page`` and ``per_page`` parameters: .. code-block:: python - ten_first_groups = gl.groups.list(page=0, per_page=10) + ten_first_groups = gl.groups.list(page=1, per_page=10) + +.. note:: + + The first page is page 1, not page 0. + By default GitLab does not return the complete list of items. Use the ``all`` parameter to get all the items when using listing methods: From 35c6bbb9dfaa49d0f080991a41eafc9dccb2e9f8 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 24 Dec 2016 14:39:10 +0100 Subject: [PATCH 05/15] [docs] artifacts example: open file in wb mode Fixes #194 --- docs/gl_objects/builds.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/gl_objects/builds.py b/docs/gl_objects/builds.py index 911fc757c..855b7c898 100644 --- a/docs/gl_objects/builds.py +++ b/docs/gl_objects/builds.py @@ -80,7 +80,7 @@ # stream artifacts class Foo(object): def __init__(self): - self._fd = open('artifacts.zip', 'w') + self._fd = open('artifacts.zip', 'wb') def __call__(self, chunk): self._fd.write(chunk) From f4fcf4550eddf5c897e432efbc3ef605d6a8a419 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 24 Dec 2016 15:03:32 +0100 Subject: [PATCH 06/15] [CLI] ignore empty arguments Gitlab 8.15 doesn't appreciate arguments with None as value. This breaks the python-gitlab CLI. Fixes #199 --- gitlab/cli.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gitlab/cli.py b/gitlab/cli.py index ec4274da6..3a80bbc6f 100644 --- a/gitlab/cli.py +++ b/gitlab/cli.py @@ -511,9 +511,12 @@ def main(): what = arg.what # Remove CLI behavior-related args - for item in ("gitlab", "config_file", "verbose", "what", "action"): + for item in ("gitlab", "config_file", "verbose", "what", "action", + "version"): args.pop(item) + args = {k: v for k, v in args.items() if v is not None} + cls = None try: cls = gitlab.__dict__[_what_to_cls(what)] From b05c0b67f8a024a67cdd16e83e70ced879e5913a Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sun, 25 Dec 2016 07:40:07 +0100 Subject: [PATCH 07/15] [CLI] Fix wrong use of arguments The previous change removed undefined arguments from the args dict, don't try to use possibly missing arguments without a fallback value. --- gitlab/cli.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gitlab/cli.py b/gitlab/cli.py index 3a80bbc6f..32b3ec850 100644 --- a/gitlab/cli.py +++ b/gitlab/cli.py @@ -181,7 +181,7 @@ def do_project_search(self, cls, gl, what, args): def do_project_all(self, cls, gl, what, args): try: - return gl.projects.all(all=args['all']) + return gl.projects.all(all=args.get('all', False)) except Exception as e: _die("Impossible to list all projects", e) @@ -333,10 +333,10 @@ def do_project_merge_request_cancel(self, cls, gl, what, args): def do_project_merge_request_merge(self, cls, gl, what, args): try: o = self.do_get(cls, gl, what, args) - should_remove = args['should_remove_source_branch'] - build_succeeds = args['merged_when_build_succeeds'] + should_remove = args.get('should_remove_source_branch', False) + build_succeeds = args.get('merged_when_build_succeeds', False) return o.merge( - merge_commit_message=args['merge_commit_message'], + merge_commit_message=args.get('merge_commit_message', ''), should_remove_source_branch=should_remove, merged_when_build_succeeds=build_succeeds) except Exception as e: From bd7d2f6d254f55fe422aa21c9e568b8d213995b8 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sun, 25 Dec 2016 10:59:32 +0100 Subject: [PATCH 08/15] [docs] Add doc for snippets --- docs/api-objects.rst | 1 + docs/gl_objects/projects.rst | 2 ++ docs/gl_objects/snippets.py | 26 +++++++++++++++++++ docs/gl_objects/snippets.rst | 48 ++++++++++++++++++++++++++++++++++++ 4 files changed, 77 insertions(+) create mode 100644 docs/gl_objects/snippets.py create mode 100644 docs/gl_objects/snippets.rst diff --git a/docs/api-objects.rst b/docs/api-objects.rst index 129667cf8..010e9d650 100644 --- a/docs/api-objects.rst +++ b/docs/api-objects.rst @@ -23,6 +23,7 @@ API objects manipulation gl_objects/projects gl_objects/runners gl_objects/settings + gl_objects/snippets gl_objects/system_hooks gl_objects/templates gl_objects/todos diff --git a/docs/gl_objects/projects.rst b/docs/gl_objects/projects.rst index bdbf140ee..584fa58f6 100644 --- a/docs/gl_objects/projects.rst +++ b/docs/gl_objects/projects.rst @@ -216,6 +216,8 @@ Delete a tag: :start-after: # tags delete :end-before: # end tags delete +.. _project_snippets: + Snippets -------- diff --git a/docs/gl_objects/snippets.py b/docs/gl_objects/snippets.py new file mode 100644 index 000000000..ca316c2d2 --- /dev/null +++ b/docs/gl_objects/snippets.py @@ -0,0 +1,26 @@ +# list +snippets = gl.snippets.list() +# end list + +# get +snippet = gl.snippets.get(snippet_id) +# get the content +content = snippet.content() +# end get + +# create +snippet = gl.snippets.create({'title': 'snippet1', + 'file_name': 'snippet1.py', + 'content': open('snippet1.py').read()}) +# end create + +# update +snippet.visibility_level = gitlab.VISIBILITY_PUBLIC +snippet.save() +# end update + +# delete +gl.snippets.delete(snippet_id) +# or +snippet.delete() +# end delete diff --git a/docs/gl_objects/snippets.rst b/docs/gl_objects/snippets.rst new file mode 100644 index 000000000..591bc95b7 --- /dev/null +++ b/docs/gl_objects/snippets.rst @@ -0,0 +1,48 @@ +######## +Snippets +######## + +You can store code snippets in Gitlab. Snippets can be attached to projects +(see :ref:`project_snippets`), but can also be detached. + +* Object class: :class:`gitlab.objects.Namespace` +* Manager object: :attr:`gitlab.Gitlab.snippets` + +Examples +======== + +List snippets: + +.. literalinclude:: snippets.py + :start-after: # list + :end-before: # end list + +Get a snippet: + +.. literalinclude:: snippets.py + :start-after: # get + :end-before: # end get + +.. warning:: + + Blobs are entirely stored in memory unless you use the streaming feature. + See :ref:`the artifacts example `. + + +Create a snippet: + +.. literalinclude:: snippets.py + :start-after: # create + :end-before: # end create + +Update a snippet: + +.. literalinclude:: snippets.py + :start-after: # update + :end-before: # end update + +Delete a snippet: + +.. literalinclude:: snippets.py + :start-after: # delete + :end-before: # end delete From 745389501281d9bcc069e86b1b41e1936132af27 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Mon, 26 Dec 2016 07:04:48 +0100 Subject: [PATCH 09/15] SnippetManager: all() -> public() Rename the method to make what it does more explicit. --- docs/gl_objects/snippets.py | 4 ++++ docs/gl_objects/snippets.rst | 8 +++++++- gitlab/objects.py | 16 ++-------------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/docs/gl_objects/snippets.py b/docs/gl_objects/snippets.py index ca316c2d2..e865b0a77 100644 --- a/docs/gl_objects/snippets.py +++ b/docs/gl_objects/snippets.py @@ -2,6 +2,10 @@ snippets = gl.snippets.list() # end list +# public list +public_snippets = gl.snippets.public() +# nd public list + # get snippet = gl.snippets.get(snippet_id) # get the content diff --git a/docs/gl_objects/snippets.rst b/docs/gl_objects/snippets.rst index 591bc95b7..34c39fba8 100644 --- a/docs/gl_objects/snippets.rst +++ b/docs/gl_objects/snippets.rst @@ -11,12 +11,18 @@ You can store code snippets in Gitlab. Snippets can be attached to projects Examples ======== -List snippets: +List snippets woned by the current user: .. literalinclude:: snippets.py :start-after: # list :end-before: # end list +List the public snippets: + +.. literalinclude:: snippets.py + :start-after: # public list + :end-before: # end public list + Get a snippet: .. literalinclude:: snippets.py diff --git a/gitlab/objects.py b/gitlab/objects.py index dcf5d5c2e..97a216573 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -1054,8 +1054,8 @@ def content(self, streamed=False, action=None, chunk_size=1024, **kwargs): class SnippetManager(BaseManager): obj_cls = Snippet - def all(self, **kwargs): - """List all the snippets + def public(self, **kwargs): + """List all the public snippets. Args: all (bool): If True, return all the items, without pagination @@ -1066,18 +1066,6 @@ def all(self, **kwargs): """ return self.gitlab._raw_list("/snippets/public", Snippet, **kwargs) - def owned(self, **kwargs): - """List owned snippets. - - Args: - all (bool): If True, return all the items, without pagination - **kwargs: Additional arguments to send to GitLab. - - Returns: - list(gitlab.Gitlab.Snippet): The list of owned snippets. - """ - return self.gitlab._raw_list("/snippets", Snippet, **kwargs) - class Namespace(GitlabObject): _url = '/namespaces' From 064e2b4bb7cb4b1775a78f51ebb46a00c9733af9 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Mon, 26 Dec 2016 07:39:37 +0100 Subject: [PATCH 10/15] Snippet: content() -> raw() Using the content() method causes conflicts with the API `content` attribute. --- docs/gl_objects/snippets.py | 4 ++-- gitlab/objects.py | 7 +++---- gitlab/tests/test_gitlabobject.py | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/docs/gl_objects/snippets.py b/docs/gl_objects/snippets.py index e865b0a77..091aef60e 100644 --- a/docs/gl_objects/snippets.py +++ b/docs/gl_objects/snippets.py @@ -9,7 +9,7 @@ # get snippet = gl.snippets.get(snippet_id) # get the content -content = snippet.content() +content = snippet.raw() # end get # create @@ -19,7 +19,7 @@ # end create # update -snippet.visibility_level = gitlab.VISIBILITY_PUBLIC +snippet.visibility_level = gitlab.Project.VISIBILITY_PUBLIC snippet.save() # end update diff --git a/gitlab/objects.py b/gitlab/objects.py index 97a216573..9ae861229 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -1026,7 +1026,7 @@ class Snippet(GitlabObject): optionalUpdateAttrs = ['title', 'file_name', 'content', 'visibility_level'] shortPrintAttr = 'title' - def content(self, streamed=False, action=None, chunk_size=1024, **kwargs): + def raw(self, streamed=False, action=None, chunk_size=1024, **kwargs): """Return the raw content of a snippet. Args: @@ -1038,14 +1038,13 @@ def content(self, streamed=False, action=None, chunk_size=1024, **kwargs): chunk_size (int): Size of each chunk. Returns: - str: The snippet content + str: The snippet content. Raises: GitlabConnectionError: If the server cannot be reached. GitlabGetError: If the server fails to perform the request. """ - url = ("/snippets/%(snippet_id)s/raw" % - {'snippet_id': self.id}) + url = ("/snippets/%(snippet_id)s/raw" % {'snippet_id': self.id}) r = self.gitlab._raw_get(url, **kwargs) raise_error_from_response(r, GitlabGetError) return utils.response_content(r, streamed, action, chunk_size) diff --git a/gitlab/tests/test_gitlabobject.py b/gitlab/tests/test_gitlabobject.py index d191c0f07..3bffb825d 100644 --- a/gitlab/tests/test_gitlabobject.py +++ b/gitlab/tests/test_gitlabobject.py @@ -483,9 +483,9 @@ def resp_content_fail(self, url, request): def test_content(self): with HTTMock(self.resp_content): data = b'content' - content = self.obj.content() + content = self.obj.raw() self.assertEqual(content, data) def test_blob_fail(self): with HTTMock(self.resp_content_fail): - self.assertRaises(GitlabGetError, self.obj.content) + self.assertRaises(GitlabGetError, self.obj.raw) From d3d8bafa22e271e75e92a3df205e533bfe2e7d11 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Mon, 26 Dec 2016 07:41:17 +0100 Subject: [PATCH 11/15] Add functional tests for Snippet --- tools/python_test.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/python_test.py b/tools/python_test.py index 0c065b8d9..abfa5087b 100644 --- a/tools/python_test.py +++ b/tools/python_test.py @@ -289,3 +289,18 @@ settings.save() settings = gl.notificationsettings.get() assert(settings.level == gitlab.NOTIFICATION_LEVEL_WATCH) + +# snippets +snippets = gl.snippets.list() +assert(len(snippets) == 0) +snippet = gl.snippets.create({'title': 'snippet1', 'file_name': 'snippet1.py', + 'content': 'import gitlab'}) +snippet = gl.snippets.get(1) +snippet.title = 'updated_title' +snippet.save() +snippet = gl.snippets.get(1) +assert(snippet.title == 'updated_title') +content = snippet.raw() +assert(content == 'import gitlab') +snippet.delete() +assert(len(gl.snippets.list()) == 0) From 73990b46d05fce5952ef9e6a6579ba1706aa72e8 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Mon, 26 Dec 2016 18:26:27 +0100 Subject: [PATCH 12/15] Fix duplicated data in API docs Fixes #190 --- docs/ext/manager_tmpl.j2 | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/ext/manager_tmpl.j2 b/docs/ext/manager_tmpl.j2 index 5a01d8f7d..fee8a568b 100644 --- a/docs/ext/manager_tmpl.j2 +++ b/docs/ext/manager_tmpl.j2 @@ -56,9 +56,6 @@ Manager for {{ cls | classref() }} objects. ``data`` is a dict defining the object attributes. Available attributes are: - {% for a in cls.requiredUrlAttrs %} - * ``{{ a }}`` (required) - {% endfor %} {% for a in cls.requiredUrlAttrs %} * ``{{ a }}`` (required if not discovered on the parent objects) {% endfor %} From 3804661f2c1336eaac0648cf9d0fc47687244e02 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Mon, 26 Dec 2016 18:41:33 +0100 Subject: [PATCH 13/15] Update known attributes for projects Fixes #181 --- gitlab/objects.py | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/gitlab/objects.py b/gitlab/objects.py index 9ae861229..7a442ef5d 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -2139,21 +2139,24 @@ class Project(GitlabObject): _url = '/projects' _constructorTypes = {'owner': 'User', 'namespace': 'Group'} requiredCreateAttrs = ['name'] - optionalCreateAttrs = ['default_branch', 'issues_enabled', 'wall_enabled', - 'merge_requests_enabled', 'wiki_enabled', + optionalCreateAttrs = ['path', 'namespace_id', 'description', + 'issues_enabled', 'merge_requests_enabled', + 'builds_enabled', 'wiki_enabled', + 'snippets_enabled', 'container_registry_enabled', + 'shared_runners_enabled', 'public', + 'visibility_level', 'import_url', 'public_builds', + 'only_allow_merge_if_build_succeeds', + 'only_allow_merge_if_all_discussions_are_resolved', + 'lfs_enabled', 'request_access_enabled'] + optionalUpdateAttrs = ['name', 'path', 'default_branch', 'description', + 'issues_enabled', 'merge_requests_enabled', + 'builds_enabled', 'wiki_enabled', 'snippets_enabled', 'container_registry_enabled', - 'public', 'visibility_level', 'namespace_id', - 'description', 'path', 'import_url', - 'builds_enabled', 'public_builds', - 'only_allow_merge_if_build_succeeds'] - optionalUpdateAttrs = ['name', 'default_branch', 'issues_enabled', - 'wall_enabled', 'merge_requests_enabled', - 'wiki_enabled', 'snippets_enabled', - 'container_registry_enabled', 'public', - 'visibility_level', 'namespace_id', 'description', - 'path', 'import_url', 'builds_enabled', - 'public_builds', - 'only_allow_merge_if_build_succeeds'] + 'shared_runners_enabled', 'public', + 'visibility_level', 'import_url', 'public_builds', + 'only_allow_merge_if_build_succeeds', + 'only_allow_merge_if_all_discussions_are_resolved', + 'lfs_enabled', 'request_access_enabled'] shortPrintAttr = 'path' managers = ( ('accessrequests', ProjectAccessRequestManager, From d6c87d956eaaeafe2bd4b0e65b42e1afdf0e10bb Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Mon, 26 Dec 2016 19:22:08 +0100 Subject: [PATCH 14/15] sudo: always use strings The behavior seems to have changed on recent gitlab releases and providing an ID as int doesn't work anymore. Using a string seems to make things work again. Fixes #193 --- gitlab/objects.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gitlab/objects.py b/gitlab/objects.py index 7a442ef5d..2a33dc518 100644 --- a/gitlab/objects.py +++ b/gitlab/objects.py @@ -222,6 +222,8 @@ def _data_for_gitlab(self, extra_parameters={}, update=False, value = getattr(self, attribute) if isinstance(value, list): value = ",".join(value) + if attribute == 'sudo': + value = str(value) data[attribute] = value data.update(extra_parameters) From 8028ec7807f18c928610ca1be36907bfc4c25f1f Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Tue, 27 Dec 2016 15:13:18 +0100 Subject: [PATCH 15/15] prepare the 0.18 release --- ChangeLog | 14 ++++++++++++++ gitlab/__init__.py | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 76932e327..e769d163f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,17 @@ +Version 0.18 + + * Fix JIRA service editing for GitLab 8.14+ + * Add jira_issue_transition_id to the JIRA service optional fields + * Added support for Snippets (new API in Gitlab 8.15) + * [docs] update pagination section + * [docs] artifacts example: open file in wb mode + * [CLI] ignore empty arguments + * [CLI] Fix wrong use of arguments + * [docs] Add doc for snippets + * Fix duplicated data in API docs + * Update known attributes for projects + * sudo: always use strings + Version 0.17 * README: add badges for pypi and RTD diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 679b023d2..e0051aafd 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -34,7 +34,7 @@ from gitlab.objects import * # noqa __title__ = 'python-gitlab' -__version__ = '0.17' +__version__ = '0.18' __author__ = 'Gauvain Pocentek' __email__ = 'gauvain@pocentek.net' __license__ = 'LGPL3'