Skip to content

Commit 92151b2

Browse files
savengerGauvain Pocentek
authored and
Gauvain Pocentek
committed
Time tracking (python-gitlab#222)
* Added gitlab time tracking features - get/set/remove estimated time per issue - get/set/remove time spent per issue * Added documentation for time tracking functions
1 parent cd69624 commit 92151b2

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

docs/gl_objects/issues.py

+20
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,23 @@
7777
# project issue todo
7878
issue.todo()
7979
# end project issue todo
80+
81+
# project issue time tracking stats
82+
issue.time_stats()
83+
# end project issue time tracking stats
84+
85+
# project issue set time estimate
86+
issue.set_time_estimate({'duration': '3h30m'})
87+
# end project issue set time estimate
88+
89+
# project issue reset time estimate
90+
issue.reset_time_estimate()
91+
# end project issue reset time estimate
92+
93+
# project issue set time spent
94+
issue.add_time_spent({'duration': '3h30m'})
95+
# end project issue set time spent
96+
97+
# project issue reset time spent
98+
issue.reset_time_spent()
99+
# end project issue reset time spent

docs/gl_objects/issues.rst

+31
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,34 @@ Make an issue as todo:
104104
.. literalinclude:: issues.py
105105
:start-after: # project issue todo
106106
:end-before: # end project issue todo
107+
108+
Get time tracking stats:
109+
110+
.. literalinclude:: issues.py
111+
:start-after: # project issue time tracking stats
112+
:end-before: # end project time tracking stats
113+
114+
Set a time estimate for an issue:
115+
116+
.. literalinclude:: issues.py
117+
:start-after: # project issue set time estimate
118+
:end-before: # end project set time estimate
119+
120+
Reset a time estimate for an issue:
121+
122+
.. literalinclude:: issues.py
123+
:start-after: # project issue reset time estimate
124+
:end-before: # end project reset time estimate
125+
126+
Add spent time for an issue:
127+
128+
.. literalinclude:: issues.py
129+
:start-after: # project issue set time spent
130+
:end-before: # end project set time spent
131+
132+
Reset spent time for an issue:
133+
134+
.. literalinclude:: issues.py
135+
:start-after: # project issue reset time spent
136+
:end-before: # end project reset time spent
137+

gitlab/exceptions.py

+4
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,10 @@ class GitlabTodoError(GitlabOperationError):
143143
pass
144144

145145

146+
class GitlabTimeTrackingError(GitlabOperationError):
147+
pass
148+
149+
146150
def raise_error_from_response(response, error, expected_code=200):
147151
"""Tries to parse gitlab error message from response and raises error.
148152

gitlab/objects.py

+63
Original file line numberDiff line numberDiff line change
@@ -1523,6 +1523,69 @@ def todo(self, **kwargs):
15231523
r = self.gitlab._raw_post(url, **kwargs)
15241524
raise_error_from_response(r, GitlabTodoError, [201, 304])
15251525

1526+
def time_stats(self, **kwargs):
1527+
"""Get time stats for the issue.
1528+
1529+
Raises:
1530+
GitlabConnectionError: If the server cannot be reached.
1531+
"""
1532+
url = ('/projects/%(project_id)s/issues/%(issue_id)s/time_stats' %
1533+
{'project_id': self.project_id, 'issue_id': self.id})
1534+
r = self.gitlab._raw_get(url, **kwargs)
1535+
raise_error_from_response(r, GitlabGetError)
1536+
return r.json()
1537+
1538+
def time_estimate(self, **kwargs):
1539+
"""Set an estimated time of work for the issue.
1540+
1541+
Raises:
1542+
GitlabConnectionError: If the server cannot be reached.
1543+
"""
1544+
url = ('/projects/%(project_id)s/issues/%(issue_id)s/time_estimate' %
1545+
{'project_id': self.project_id, 'issue_id': self.id})
1546+
r = self.gitlab._raw_post(url, **kwargs)
1547+
raise_error_from_response(r, GitlabTimeTrackingError, 201)
1548+
return r.json()
1549+
1550+
def reset_time_estimate(self, **kwargs):
1551+
"""Resets estimated time for the issue to 0 seconds.
1552+
1553+
Raises:
1554+
GitlabConnectionError: If the server cannot be reached.
1555+
"""
1556+
url = ('/projects/%(project_id)s/issues/%(issue_id)s/'
1557+
'reset_time_estimate' %
1558+
{'project_id': self.project_id, 'issue_id': self.id})
1559+
r = self.gitlab._raw_post(url, **kwargs)
1560+
raise_error_from_response(r, GitlabTimeTrackingError, 200)
1561+
return r.json()
1562+
1563+
def add_spent_time(self, **kwargs):
1564+
"""Set an estimated time of work for the issue.
1565+
1566+
Raises:
1567+
GitlabConnectionError: If the server cannot be reached.
1568+
"""
1569+
url = ('/projects/%(project_id)s/issues/%(issue_id)s/'
1570+
'reset_spent_time' %
1571+
{'project_id': self.project_id, 'issue_id': self.id})
1572+
r = self.gitlab._raw_post(url, **kwargs)
1573+
raise_error_from_response(r, GitlabTimeTrackingError, 200)
1574+
return r.json()
1575+
1576+
def reset_spent_time(self, **kwargs):
1577+
"""Set an estimated time of work for the issue.
1578+
1579+
Raises:
1580+
GitlabConnectionError: If the server cannot be reached.
1581+
"""
1582+
url = ('/projects/%(project_id)s/issues/%(issue_id)s/'
1583+
'add_spent_time' %
1584+
{'project_id': self.project_id, 'issue_id': self.id})
1585+
r = self.gitlab._raw_post(url, **kwargs)
1586+
raise_error_from_response(r, GitlabTimeTrackingError, 200)
1587+
return r.json()
1588+
15261589

15271590
class ProjectIssueManager(BaseManager):
15281591
obj_cls = ProjectIssue

0 commit comments

Comments
 (0)