From a3b88583d05274b5e858ee0cd198f925ad22d4d0 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 07:43:54 +0200 Subject: [PATCH 01/11] install doc: use sudo for system commands Fixes #267 --- docs/install.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/install.rst b/docs/install.rst index 6a1887359..1bc6d1706 100644 --- a/docs/install.rst +++ b/docs/install.rst @@ -8,7 +8,7 @@ Use :command:`pip` to install the latest stable version of ``python-gitlab``: .. code-block:: console - $ pip install --upgrade python-gitlab + $ sudo pip install --upgrade python-gitlab The current development version is available on `github `__. Use :command:`git` and @@ -18,4 +18,4 @@ The current development version is available on `github $ git clone https://github.com/python-gitlab/python-gitlab $ cd python-gitlab - $ python setup.py install + $ sudo python setup.py install From 1ab9ff06027a478ebedb7840db71cd308da65161 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 08:06:19 +0200 Subject: [PATCH 02/11] [v4] Make MR work properly * Use iids instead of ids (Fixes #266) * Add required duration argument for time_estimate() and add_spent_time() --- gitlab/v4/objects.py | 76 +++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index b86d8bee9..309bb7856 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -1090,11 +1090,11 @@ class ProjectTagManager(BaseManager): class ProjectMergeRequestDiff(GitlabObject): _url = ('/projects/%(project_id)s/merge_requests/' - '%(merge_request_id)s/versions') + '%(merge_request_iid)s/versions') canCreate = False canUpdate = False canDelete = False - requiredUrlAttrs = ['project_id', 'merge_request_id'] + requiredUrlAttrs = ['project_id', 'merge_request_iid'] class ProjectMergeRequestDiffManager(BaseManager): @@ -1102,9 +1102,9 @@ class ProjectMergeRequestDiffManager(BaseManager): class ProjectMergeRequestNote(GitlabObject): - _url = '/projects/%(project_id)s/merge_requests/%(merge_request_id)s/notes' + _url = '/projects/%(project_id)s/merge_requests/%(merge_request_iid)s/notes' _constructorTypes = {'author': 'User'} - requiredUrlAttrs = ['project_id', 'merge_request_id'] + requiredUrlAttrs = ['project_id', 'merge_request_iid'] requiredCreateAttrs = ['body'] @@ -1123,12 +1123,13 @@ class ProjectMergeRequest(GitlabObject): 'description', 'state_event', 'labels', 'milestone_id'] optionalListAttrs = ['iids', 'state', 'order_by', 'sort'] + idAttr = 'iid' managers = ( ('notes', 'ProjectMergeRequestNoteManager', - [('project_id', 'project_id'), ('merge_request_id', 'id')]), + [('project_id', 'project_id'), ('merge_request_iid', 'iid')]), ('diffs', 'ProjectMergeRequestDiffManager', - [('project_id', 'project_id'), ('merge_request_id', 'id')]), + [('project_id', 'project_id'), ('merge_request_iid', 'iid')]), ) def _data_for_gitlab(self, extra_parameters={}, update=False, @@ -1149,9 +1150,9 @@ def subscribe(self, **kwargs): GitlabConnectionError: If the server cannot be reached. GitlabSubscribeError: If the subscription cannot be done """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/' + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' 'subscribe' % - {'project_id': self.project_id, 'mr_id': self.id}) + {'project_id': self.project_id, 'mr_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabSubscribeError, [201, 304]) @@ -1165,9 +1166,9 @@ def unsubscribe(self, **kwargs): GitlabConnectionError: If the server cannot be reached. GitlabUnsubscribeError: If the unsubscription cannot be done """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/' + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' 'unsubscribe' % - {'project_id': self.project_id, 'mr_id': self.id}) + {'project_id': self.project_id, 'mr_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabUnsubscribeError, [201, 304]) @@ -1179,7 +1180,7 @@ def cancel_merge_when_pipeline_succeeds(self, **kwargs): u = ('/projects/%s/merge_requests/%s/' 'cancel_merge_when_pipeline_succeeds' - % (self.project_id, self.id)) + % (self.project_id, self.iid)) r = self.gitlab._raw_put(u, **kwargs) errors = {401: GitlabMRForbiddenError, 405: GitlabMRClosedError, @@ -1198,7 +1199,7 @@ def closes_issues(self, **kwargs): GitlabGetError: If the server fails to perform the request. """ url = ('/projects/%s/merge_requests/%s/closes_issues' % - (self.project_id, self.id)) + (self.project_id, self.iid)) return self.gitlab._raw_list(url, ProjectIssue, {'project_id': self.project_id}, **kwargs) @@ -1214,7 +1215,7 @@ def commits(self, **kwargs): GitlabListError: If the server fails to perform the request. """ url = ('/projects/%s/merge_requests/%s/commits' % - (self.project_id, self.id)) + (self.project_id, self.iid)) return self.gitlab._raw_list(url, ProjectCommit, {'project_id': self.project_id}, **kwargs) @@ -1230,7 +1231,7 @@ def changes(self, **kwargs): GitlabListError: If the server fails to perform the request. """ url = ('/projects/%s/merge_requests/%s/changes' % - (self.project_id, self.id)) + (self.project_id, self.iid)) r = self.gitlab._raw_get(url, **kwargs) raise_error_from_response(r, GitlabListError) return r.json() @@ -1257,7 +1258,7 @@ def merge(self, merge_commit_message=None, GitlabMRClosedError: If the MR is already closed """ url = '/projects/%s/merge_requests/%s/merge' % (self.project_id, - self.id) + self.iid) data = {} if merge_commit_message: data['merge_commit_message'] = merge_commit_message @@ -1278,8 +1279,8 @@ def todo(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/todo' % - {'project_id': self.project_id, 'mr_id': self.id}) + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/todo' % + {'project_id': self.project_id, 'mr_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabTodoError, [201, 304]) @@ -1289,23 +1290,28 @@ def time_stats(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/time_stats' % - {'project_id': self.project_id, 'mr_id': self.id}) + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' + 'time_stats' % + {'project_id': self.project_id, 'mr_iid': self.iid}) r = self.gitlab._raw_get(url, **kwargs) raise_error_from_response(r, GitlabGetError) return r.json() - def time_estimate(self, **kwargs): + def time_estimate(self, duration, **kwargs): """Set an estimated time of work for the merge request. + Args: + duration (str): duration in human format (e.g. 3h30) + Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/' + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' 'time_estimate' % - {'project_id': self.project_id, 'mr_id': self.id}) - r = self.gitlab._raw_post(url, **kwargs) - raise_error_from_response(r, GitlabTimeTrackingError, 201) + {'project_id': self.project_id, 'mr_iid': self.iid}) + data = {'duration': duration} + r = self.gitlab._raw_post(url, data, **kwargs) + raise_error_from_response(r, GitlabTimeTrackingError, 200) return r.json() def reset_time_estimate(self, **kwargs): @@ -1314,24 +1320,28 @@ def reset_time_estimate(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/' + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' 'reset_time_estimate' % - {'project_id': self.project_id, 'mr_id': self.id}) + {'project_id': self.project_id, 'mr_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabTimeTrackingError, 200) return r.json() - def add_spent_time(self, **kwargs): + def add_spent_time(self, duration, **kwargs): """Set an estimated time of work for the merge request. + Args: + duration (str): duration in human format (e.g. 3h30) + Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/' + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' 'add_spent_time' % - {'project_id': self.project_id, 'mr_id': self.id}) - r = self.gitlab._raw_post(url, **kwargs) - raise_error_from_response(r, GitlabTimeTrackingError, 200) + {'project_id': self.project_id, 'mr_iid': self.iid}) + data = {'duration': duration} + r = self.gitlab._raw_post(url, data, **kwargs) + raise_error_from_response(r, GitlabTimeTrackingError, 201) return r.json() def reset_spent_time(self, **kwargs): @@ -1340,9 +1350,9 @@ def reset_spent_time(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/merge_requests/%(mr_id)s/' + url = ('/projects/%(project_id)s/merge_requests/%(mr_iid)s/' 'reset_spent_time' % - {'project_id': self.project_id, 'mr_id': self.id}) + {'project_id': self.project_id, 'mr_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabTimeTrackingError, 200) return r.json() From f733ffb1c1ac2243c14c660bfac98443c1a7e67c Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 08:19:21 +0200 Subject: [PATCH 03/11] Fix python functional tests --- gitlab/base.py | 2 +- tools/python_test.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gitlab/base.py b/gitlab/base.py index aa660b24e..0d82cf1fc 100644 --- a/gitlab/base.py +++ b/gitlab/base.py @@ -431,7 +431,7 @@ def __getattr__(self, name): self._set_manager(var, cls, attrs) return getattr(self, var) - raise AttributeError + raise AttributeError(name) def __str__(self): return '%s => %s' % (type(self), str(self.__dict__)) diff --git a/tools/python_test.py b/tools/python_test.py index b56a97db9..62d64213a 100644 --- a/tools/python_test.py +++ b/tools/python_test.py @@ -85,7 +85,7 @@ new_user.delete() foobar_user.delete() -assert(len(gl.users.list()) == 1) +assert(len(gl.users.list()) == 3) # current user key key = gl.user.keys.create({'title': 'testkey', 'key': SSH_KEY}) @@ -163,7 +163,7 @@ readme.content = base64.b64encode("Improved README") time.sleep(2) readme.save(branch_name="master", commit_message="new commit") -readme.delete(commit_message="Removing README") +readme.delete(commit_message="Removing README", branch_name="master") admin_project.files.create({'file_path': 'README.rst', 'branch_name': 'master', From 06631847a7184cb22e28cd170c034a4d6d16fe8f Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 08:20:38 +0200 Subject: [PATCH 04/11] pep8 fix --- gitlab/v4/objects.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 309bb7856..48ece816d 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -1102,7 +1102,8 @@ class ProjectMergeRequestDiffManager(BaseManager): class ProjectMergeRequestNote(GitlabObject): - _url = '/projects/%(project_id)s/merge_requests/%(merge_request_iid)s/notes' + _url = ('/projects/%(project_id)s/merge_requests/%(merge_request_iid)s' + '/notes') _constructorTypes = {'author': 'User'} requiredUrlAttrs = ['project_id', 'merge_request_iid'] requiredCreateAttrs = ['body'] From f3b28553aaa5e4e71df7892ea6c34fcc8dc61f90 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 08:28:46 +0200 Subject: [PATCH 05/11] Remove extra_attrs argument from _raw_list (unneeded) --- gitlab/__init__.py | 6 ++---- gitlab/v3/objects.py | 20 +++++--------------- gitlab/v4/objects.py | 16 ++++------------ 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/gitlab/__init__.py b/gitlab/__init__.py index e6024a873..4adc5630d 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -344,9 +344,8 @@ def _raw_get(self, path_, content_type=None, streamed=False, **kwargs): raise GitlabConnectionError( "Can't connect to GitLab server (%s)" % e) - def _raw_list(self, path_, cls, extra_attrs={}, **kwargs): - params = extra_attrs.copy() - params.update(kwargs.copy()) + def _raw_list(self, path_, cls, **kwargs): + params = kwargs.copy() catch_recursion_limit = kwargs.get('safe_all', False) get_all_results = (kwargs.get('all', False) is True @@ -376,7 +375,6 @@ def _raw_list(self, path_, cls, extra_attrs={}, **kwargs): if ('next' in r.links and 'url' in r.links['next'] and get_all_results): args = kwargs.copy() - args.update(extra_attrs) args['next_url'] = r.links['next']['url'] results.extend(self.list(cls, **args)) except Exception as e: diff --git a/gitlab/v3/objects.py b/gitlab/v3/objects.py index 01bb67040..b2fd18044 100644 --- a/gitlab/v3/objects.py +++ b/gitlab/v3/objects.py @@ -799,9 +799,7 @@ def builds(self, **kwargs): """ url = '/projects/%s/repository/commits/%s/builds' % (self.project_id, self.id) - return self.gitlab._raw_list(url, ProjectBuild, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectBuild, **kwargs) def cherry_pick(self, branch, **kwargs): """Cherry-pick a commit into a branch. @@ -1254,9 +1252,7 @@ def closes_issues(self, **kwargs): """ url = ('/projects/%s/merge_requests/%s/closes_issues' % (self.project_id, self.id)) - return self.gitlab._raw_list(url, ProjectIssue, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectIssue, **kwargs) def commits(self, **kwargs): """List the merge request commits. @@ -1270,9 +1266,7 @@ def commits(self, **kwargs): """ url = ('/projects/%s/merge_requests/%s/commits' % (self.project_id, self.id)) - return self.gitlab._raw_list(url, ProjectCommit, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectCommit, **kwargs) def changes(self, **kwargs): """List the merge request changes. @@ -1420,9 +1414,7 @@ class ProjectMilestone(GitlabObject): def issues(self, **kwargs): url = "/projects/%s/milestones/%s/issues" % (self.project_id, self.id) - return self.gitlab._raw_list(url, ProjectIssue, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectIssue, **kwargs) def merge_requests(self, **kwargs): """List the merge requests related to this milestone @@ -1436,9 +1428,7 @@ def merge_requests(self, **kwargs): """ url = ('/projects/%s/milestones/%s/merge_requests' % (self.project_id, self.id)) - return self.gitlab._raw_list(url, ProjectMergeRequest, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectMergeRequest, **kwargs) class ProjectMilestoneManager(BaseManager): diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 48ece816d..a511e07a4 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -1201,9 +1201,7 @@ def closes_issues(self, **kwargs): """ url = ('/projects/%s/merge_requests/%s/closes_issues' % (self.project_id, self.iid)) - return self.gitlab._raw_list(url, ProjectIssue, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectIssue, **kwargs) def commits(self, **kwargs): """List the merge request commits. @@ -1217,9 +1215,7 @@ def commits(self, **kwargs): """ url = ('/projects/%s/merge_requests/%s/commits' % (self.project_id, self.iid)) - return self.gitlab._raw_list(url, ProjectCommit, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectCommit, **kwargs) def changes(self, **kwargs): """List the merge request changes. @@ -1376,9 +1372,7 @@ class ProjectMilestone(GitlabObject): def issues(self, **kwargs): url = "/projects/%s/milestones/%s/issues" % (self.project_id, self.id) - return self.gitlab._raw_list(url, ProjectIssue, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectIssue, **kwargs) def merge_requests(self, **kwargs): """List the merge requests related to this milestone @@ -1392,9 +1386,7 @@ def merge_requests(self, **kwargs): """ url = ('/projects/%s/milestones/%s/merge_requests' % (self.project_id, self.id)) - return self.gitlab._raw_list(url, ProjectMergeRequest, - {'project_id': self.project_id}, - **kwargs) + return self.gitlab._raw_list(url, ProjectMergeRequest, **kwargs) class ProjectMilestoneManager(BaseManager): From ac3aef64d8d1275a457fc4164cafda85c2a42b1a Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 08:42:24 +0200 Subject: [PATCH 06/11] [v4] Make project issues work properly * Use iids instead of ids * Add required duration argument for time_estimate() and add_spent_time() --- gitlab/v4/objects.py | 63 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 27 deletions(-) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index a511e07a4..83790bfac 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -850,10 +850,10 @@ class ProjectHookManager(BaseManager): class ProjectIssueNote(GitlabObject): - _url = '/projects/%(project_id)s/issues/%(issue_id)s/notes' + _url = '/projects/%(project_id)s/issues/%(issue_iid)s/notes' _constructorTypes = {'author': 'User'} canDelete = False - requiredUrlAttrs = ['project_id', 'issue_id'] + requiredUrlAttrs = ['project_id', 'issue_iid'] requiredCreateAttrs = ['body'] optionalCreateAttrs = ['created_at'] @@ -875,9 +875,10 @@ class ProjectIssue(GitlabObject): 'milestone_id', 'labels', 'created_at', 'updated_at', 'state_event', 'due_date'] shortPrintAttr = 'title' + idAttr = 'iid' managers = ( ('notes', 'ProjectIssueNoteManager', - [('project_id', 'project_id'), ('issue_id', 'id')]), + [('project_id', 'project_id'), ('issue_iid', 'iid')]), ) def subscribe(self, **kwargs): @@ -887,8 +888,8 @@ def subscribe(self, **kwargs): GitlabConnectionError: If the server cannot be reached. GitlabSubscribeError: If the subscription cannot be done """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/subscribe' % - {'project_id': self.project_id, 'issue_id': self.id}) + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/subscribe' % + {'project_id': self.project_id, 'issue_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabSubscribeError, [201, 304]) @@ -901,8 +902,8 @@ def unsubscribe(self, **kwargs): GitlabConnectionError: If the server cannot be reached. GitlabUnsubscribeError: If the unsubscription cannot be done """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/unsubscribe' % - {'project_id': self.project_id, 'issue_id': self.id}) + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/unsubscribe' % + {'project_id': self.project_id, 'issue_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabUnsubscribeError, [201, 304]) @@ -914,8 +915,8 @@ def move(self, to_project_id, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/move' % - {'project_id': self.project_id, 'issue_id': self.id}) + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/move' % + {'project_id': self.project_id, 'issue_iid': self.iid}) data = {'to_project_id': to_project_id} data.update(**kwargs) @@ -929,8 +930,8 @@ def todo(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/todo' % - {'project_id': self.project_id, 'issue_id': self.id}) + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/todo' % + {'project_id': self.project_id, 'issue_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabTodoError, [201, 304]) @@ -940,22 +941,26 @@ def time_stats(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/time_stats' % - {'project_id': self.project_id, 'issue_id': self.id}) + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/time_stats' % + {'project_id': self.project_id, 'issue_iid': self.iid}) r = self.gitlab._raw_get(url, **kwargs) raise_error_from_response(r, GitlabGetError) return r.json() - def time_estimate(self, **kwargs): + def time_estimate(self, duration, **kwargs): """Set an estimated time of work for the issue. + Args: + duration (str): duration in human format (e.g. 3h30) + Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/time_estimate' % - {'project_id': self.project_id, 'issue_id': self.id}) - r = self.gitlab._raw_post(url, **kwargs) - raise_error_from_response(r, GitlabTimeTrackingError, 201) + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/time_estimate' % + {'project_id': self.project_id, 'issue_iid': self.iid}) + data = {'duration': duration} + r = self.gitlab._raw_post(url, data, **kwargs) + raise_error_from_response(r, GitlabTimeTrackingError, 200) return r.json() def reset_time_estimate(self, **kwargs): @@ -964,24 +969,28 @@ def reset_time_estimate(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/' + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/' 'reset_time_estimate' % - {'project_id': self.project_id, 'issue_id': self.id}) + {'project_id': self.project_id, 'issue_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabTimeTrackingError, 200) return r.json() - def add_spent_time(self, **kwargs): + def add_spent_time(self, duration, **kwargs): """Set an estimated time of work for the issue. + Args: + duration (str): duration in human format (e.g. 3h30) + Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/' + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/' 'add_spent_time' % - {'project_id': self.project_id, 'issue_id': self.id}) - r = self.gitlab._raw_post(url, **kwargs) - raise_error_from_response(r, GitlabTimeTrackingError, 200) + {'project_id': self.project_id, 'issue_iid': self.iid}) + data = {'duration': duration} + r = self.gitlab._raw_post(url, data, **kwargs) + raise_error_from_response(r, GitlabTimeTrackingError, 201) return r.json() def reset_spent_time(self, **kwargs): @@ -990,9 +999,9 @@ def reset_spent_time(self, **kwargs): Raises: GitlabConnectionError: If the server cannot be reached. """ - url = ('/projects/%(project_id)s/issues/%(issue_id)s/' + url = ('/projects/%(project_id)s/issues/%(issue_iid)s/' 'reset_spent_time' % - {'project_id': self.project_id, 'issue_id': self.id}) + {'project_id': self.project_id, 'issue_iid': self.iid}) r = self.gitlab._raw_post(url, **kwargs) raise_error_from_response(r, GitlabTimeTrackingError, 200) return r.json() From 38bff3eb43ee6526b3e3b35c8207fac9ef9bc9d9 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sat, 27 May 2017 08:51:21 +0200 Subject: [PATCH 07/11] Prepare for v4 API testing --- tools/build_test_env.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/build_test_env.sh b/tools/build_test_env.sh index 3f6191a2a..96d341a9a 100755 --- a/tools/build_test_env.sh +++ b/tools/build_test_env.sh @@ -26,9 +26,11 @@ fatal() { error "$@"; exit 1; } try() { "$@" || fatal "'$@' failed"; } PY_VER=2 -while getopts :p: opt "$@"; do +API_VER=3 +while getopts :p:a: opt "$@"; do case $opt in p) PY_VER=$OPTARG;; + a) API_VER=$OPTARG;; :) fatal "Option -${OPTARG} requires a value";; '?') fatal "Unknown option: -${OPTARG}";; *) fatal "Internal error: opt=${opt}";; @@ -41,6 +43,11 @@ case $PY_VER in *) fatal "Wrong python version (2 or 3)";; esac +case $API_VER in + 3|4) ;; + *) fatal "Wrong API version (3 or 4)";; +esac + for req in \ curl \ docker \ @@ -130,6 +137,7 @@ timeout = 10 [local] url = http://localhost:8080 private_token = $TOKEN +api_version = $API_VER EOF log "Config file content ($CONFIG):" From 88900e06761794442716c115229bd1f780cfbcef Mon Sep 17 00:00:00 2001 From: Cosimo Lupo Date: Fri, 2 Jun 2017 14:41:06 +0100 Subject: [PATCH 08/11] import urlencode() from six.moves.urllib.parse instead of from urllib (#268) Fixes AttributeError on Python 3, as `urlencode` function has been moved to `urllib.parse` module. `six.moves.urllib.parse.urlencode()` is an py2.py3 compatible alias of `urllib.parse.urlencode()` on Python 3, and of `urllib.urlencode()` on Python 2. --- gitlab/v3/objects.py | 6 +++--- gitlab/v4/objects.py | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/gitlab/v3/objects.py b/gitlab/v3/objects.py index b2fd18044..84b9cb558 100644 --- a/gitlab/v3/objects.py +++ b/gitlab/v3/objects.py @@ -20,10 +20,10 @@ from __future__ import absolute_import import base64 import json -import urllib import warnings import six +from six.moves import urllib import gitlab from gitlab.base import * # noqa @@ -1841,7 +1841,7 @@ def repository_tree(self, path='', ref_name='', **kwargs): url = "/projects/%s/repository/tree" % (self.id) params = [] if path: - params.append(urllib.urlencode({'path': path})) + params.append(urllib.parse.urlencode({'path': path})) if ref_name: params.append("ref_name=%s" % ref_name) if params: @@ -1872,7 +1872,7 @@ def repository_blob(self, sha, filepath, streamed=False, action=None, GitlabGetError: If the server fails to perform the request. """ url = "/projects/%s/repository/blobs/%s" % (self.id, sha) - url += '?%s' % (urllib.urlencode({'filepath': filepath})) + url += '?%s' % (urllib.parse.urlencode({'filepath': filepath})) r = self.gitlab._raw_get(url, streamed=streamed, **kwargs) raise_error_from_response(r, GitlabGetError) return utils.response_content(r, streamed, action, chunk_size) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 83790bfac..628314994 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -20,9 +20,9 @@ from __future__ import absolute_import import base64 import json -import urllib import six +from six.moves import urllib import gitlab from gitlab.base import * # noqa @@ -1846,7 +1846,7 @@ def repository_tree(self, path='', ref='', **kwargs): url = "/projects/%s/repository/tree" % (self.id) params = [] if path: - params.append(urllib.urlencode({'path': path})) + params.append(urllib.parse.urlencode({'path': path})) if ref: params.append("ref=%s" % ref) if params: From 2b1e0f0041ae04134d38a5db47cc301aa757d7ea Mon Sep 17 00:00:00 2001 From: Nathan Giesbrecht Date: Fri, 2 Jun 2017 08:43:55 -0500 Subject: [PATCH 09/11] Fixed spelling mistake (#269) --- docs/cli.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/cli.rst b/docs/cli.rst index 6730c9bf6..f0ed2ee2e 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -49,9 +49,9 @@ The configuration file uses the ``INI`` format. It contains at least a timeout = 1 The ``default`` option of the ``[global]`` section defines the GitLab server to -use if no server is explitly specified with the ``--gitlab`` CLI option. +use if no server is explicitly specified with the ``--gitlab`` CLI option. -The ``[global]`` section also defines the values for the default connexion +The ``[global]`` section also defines the values for the default connection parameters. You can override the values in each GitLab server section. .. list-table:: Global options From 1a58f7e522bb4784e2127582b2d46d6991a8f2a9 Mon Sep 17 00:00:00 2001 From: Jamie Bliss Date: Mon, 5 Jun 2017 18:15:55 -0400 Subject: [PATCH 10/11] Add new event types to ProjectHook These are being returned in the live API, but can't set them. --- gitlab/v4/objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab/v4/objects.py b/gitlab/v4/objects.py index 628314994..d1d589e71 100644 --- a/gitlab/v4/objects.py +++ b/gitlab/v4/objects.py @@ -841,7 +841,7 @@ class ProjectHook(GitlabObject): optionalCreateAttrs = ['push_events', 'issues_events', 'note_events', 'merge_requests_events', 'tag_push_events', 'build_events', 'enable_ssl_verification', 'token', - 'pipeline_events'] + 'pipeline_events', 'job_events', 'wiki_page_events'] shortPrintAttr = 'url' From 19f1b1a968aba7bd9604511c015e8930e5111324 Mon Sep 17 00:00:00 2001 From: Gauvain Pocentek Date: Sun, 11 Jun 2017 13:56:49 +0200 Subject: [PATCH 11/11] 0.21.2 release --- AUTHORS | 3 +++ ChangeLog.rst | 12 ++++++++++++ gitlab/__init__.py | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/AUTHORS b/AUTHORS index 9a11b3cfa..d95dad8c5 100644 --- a/AUTHORS +++ b/AUTHORS @@ -20,6 +20,7 @@ Asher256@users.noreply.github.com Christian Christian Wenk Colin D Bennett +Cosimo Lupo Crestez Dan Leonard Daniel Kimsey derek-austin @@ -35,6 +36,7 @@ Ian Sparks itxaka Ivica Arsov James (d0c_s4vage) Johnson +Jamie Bliss James E. Flemer James Johnson Jason Antman @@ -50,6 +52,7 @@ Michal Galet Mikhail Lopotkov Missionrulz Mond WAN +Nathan Giesbrecht pa4373 Patrick Miller Peng Xiao diff --git a/ChangeLog.rst b/ChangeLog.rst index 306a730a9..a72ac6f24 100644 --- a/ChangeLog.rst +++ b/ChangeLog.rst @@ -1,6 +1,17 @@ ChangeLog ========= +Version 0.21.2_ - 2017-06-11 +---------------------------- + +* Install doc: use sudo for system commands +* [v4] Make MR work properly +* Remove extra_attrs argument from _raw_list +* [v4] Make project issues work properly +* Fix urlencode() usage (python 2/3) (#268) +* Fixed spelling mistake (#269) +* Add new event types to ProjectHook + Version 0.21.1_ - 2017-05-25 ---------------------------- @@ -423,6 +434,7 @@ Version 0.1 - 2013-07-08 * Initial release +.. _0.21.2: https://github.com/python-gitlab/python-gitlab/compare/0.21.1...0.21.2 .. _0.21.1: https://github.com/python-gitlab/python-gitlab/compare/0.21...0.21.1 .. _0.21: https://github.com/python-gitlab/python-gitlab/compare/0.20...0.21 .. _0.20: https://github.com/python-gitlab/python-gitlab/compare/0.19...0.20 diff --git a/gitlab/__init__.py b/gitlab/__init__.py index 4adc5630d..97e937d70 100644 --- a/gitlab/__init__.py +++ b/gitlab/__init__.py @@ -35,7 +35,7 @@ from gitlab.v3.objects import * # noqa __title__ = 'python-gitlab' -__version__ = '0.21.1' +__version__ = '0.21.2' __author__ = 'Gauvain Pocentek' __email__ = 'gauvain@pocentek.net' __license__ = 'LGPL3'