Skip to content

Commit

Permalink
Implement decorators for handling resource arguments in JIRA client c…
Browse files Browse the repository at this point in the history
…alls
  • Loading branch information
Ben Speakmon committed May 30, 2012
1 parent c45e7a7 commit dd67e66
Show file tree
Hide file tree
Showing 3 changed files with 257 additions and 7 deletions.
4 changes: 4 additions & 0 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ which pip can also set up for you::
Doing this creates a private Python "installation" that you can freely upgrade, degrade or break without putting
the critical components of your system at risk.

Source packages are also available at PyPI:

http://pypi.python.org/pypi/jira-python/

Dependencies
------------

Expand Down
49 changes: 49 additions & 0 deletions jira/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,29 @@
responses from JIRA and the Resource/dict abstractions provided by this library. Users
will construct a JIRA object as described below.
"""
from functools import wraps

import requests
import json
from jira.exceptions import JIRAError
from jira.resources import Resource, Issue, Comment, Project, Attachment, Component, Dashboard, Filter, Votes, Watchers, Worklog, IssueLink, IssueLinkType, IssueType, Priority, Version, Role, Resolution, SecurityLevel, Status, User, CustomFieldOption, RemoteLink

def translate_resource_args(func):
"""
Decorator that converts Issue and Project resources to their keys when used as arguments.
"""
@wraps(func)
def wrapper(*args, **kwargs):
arg_list = []
for arg in args:
if isinstance(arg, (Issue, Project)):
arg_list.append(arg.key)
else:
arg_list.append(arg)
result = func(*arg_list, **kwargs)
return result
return wrapper

class JIRA(object):
"""
User interface to JIRA.
Expand Down Expand Up @@ -136,6 +153,7 @@ def attachment_meta(self):
"""Get the attachment metadata."""
return self._get_json('attachment/meta')

@translate_resource_args
def add_attachment(self, issue, attachment):
"""
Attach an attachment to an issue and returns a Resource for it.
Expand Down Expand Up @@ -168,6 +186,7 @@ def component(self, id):
"""
return self._find_for_resource(Component, id)

@translate_resource_args
def create_component(self, name, project, description=None, leadUserName=None, assigneeType=None,
isAssigneeTypeValid=False):
"""
Expand Down Expand Up @@ -373,6 +392,7 @@ def createmeta(self, projectKeys=None, projectIds=None, issuetypeIds=None, issue
return self._get_json('issue/createmeta', params)

# non-resource
@translate_resource_args
def assign_issue(self, issue, assignee):
"""
Assign an issue to a user.
Expand All @@ -385,6 +405,7 @@ def assign_issue(self, issue, assignee):
r = self._session.put(url, data=json.dumps(payload))
self._raise_on_error(r)

@translate_resource_args
def comments(self, issue):
"""
Get a list of comment Resources.
Expand All @@ -396,6 +417,7 @@ def comments(self, issue):
comments = [Comment(self._options, self._session, raw_comment_json) for raw_comment_json in r_json['comments']]
return comments

@translate_resource_args
def comment(self, issue, comment):
"""
Get a comment Resource from the server for the specified ID.
Expand All @@ -405,6 +427,7 @@ def comment(self, issue, comment):
"""
return self._find_for_resource(Comment, (issue, comment))

@translate_resource_args
def add_comment(self, issue, body, visibility=None):
"""
Add a comment from the current authenticated user on the specified issue and return a Resource for it.
Expand All @@ -430,6 +453,7 @@ def add_comment(self, issue, body, visibility=None):
return comment

# non-resource
@translate_resource_args
def editmeta(self, issue):
"""
Get the edit metadata for an issue.
Expand All @@ -438,6 +462,7 @@ def editmeta(self, issue):
"""
return self._get_json('issue/' + issue + '/editmeta')

@translate_resource_args
def remote_links(self, issue):
"""
Get a list of remote link Resources from an issue.
Expand All @@ -448,6 +473,7 @@ def remote_links(self, issue):
remote_links = [RemoteLink(self._options, self._session, raw_remotelink_json) for raw_remotelink_json in r_json]
return remote_links

@translate_resource_args
def remote_link(self, issue, id):
"""
Get a remote link Resource from the server.
Expand All @@ -457,6 +483,7 @@ def remote_link(self, issue, id):
"""
return self._find_for_resource(RemoteLink, (issue, id))

@translate_resource_args
def add_remote_link(self, issue, object, globalId=None, application=None, relationship=None):
"""
Create a remote link from an issue to an external application and returns a remote link Resource
Expand Down Expand Up @@ -490,6 +517,7 @@ def add_remote_link(self, issue, object, globalId=None, application=None, relati
return remote_link

# non-resource
@translate_resource_args
def transitions(self, issue, id=None, expand=None):
"""
Get a list of the transitions available on the specified issue to the current user.
Expand All @@ -505,6 +533,7 @@ def transitions(self, issue, id=None, expand=None):
params['expand'] = expand
return self._get_json('issue/' + issue + '/transitions', params)['transitions']

@translate_resource_args
def transition_issue(self, issue, transitionId, fields=None, **fieldargs):
# TODO: Support update verbs (same as issue.update())
"""
Expand Down Expand Up @@ -536,6 +565,7 @@ def transition_issue(self, issue, transitionId, fields=None, **fieldargs):
r = self._session.post(url, data=json.dumps(data))
self._raise_on_error(r)

@translate_resource_args
def votes(self, issue):
"""
Get a votes Resource from the server.
Expand All @@ -544,6 +574,7 @@ def votes(self, issue):
"""
return self._find_for_resource(Votes, issue)

@translate_resource_args
def add_vote(self, issue):
"""
Register a vote for the current authenticated user on an issue.
Expand All @@ -553,6 +584,7 @@ def add_vote(self, issue):
url = self._get_url('issue/' + issue + '/votes')
self._session.post(url)

@translate_resource_args
def remove_vote(self, issue):
"""
Remove the current authenticated user's vote from an issue.
Expand All @@ -562,6 +594,7 @@ def remove_vote(self, issue):
url = self._get_url('issue/' + issue + '/votes')
self._session.delete(url)

@translate_resource_args
def watchers(self, issue):
"""
Get a watchers Resource from the server for an issue.
Expand All @@ -570,6 +603,7 @@ def watchers(self, issue):
"""
return self._find_for_resource(Watchers, issue)

@translate_resource_args
def add_watcher(self, issue, watcher):
"""
Add a user to an issue's watchers list.
Expand All @@ -580,6 +614,7 @@ def add_watcher(self, issue, watcher):
url = self._get_url('issue/' + issue + '/watchers')
r = self._session.post(url, data=json.dumps(watcher))

@translate_resource_args
def remove_watcher(self, issue, watcher):
"""
Remove a user from an issue's watch list.
Expand All @@ -591,6 +626,7 @@ def remove_watcher(self, issue, watcher):
params = {'username': watcher}
self._session.delete(url, params=params)

@translate_resource_args
def worklogs(self, issue):
"""
Get a list of worklog Resources from the server for an issue.
Expand All @@ -601,6 +637,7 @@ def worklogs(self, issue):
worklogs = [Worklog(self._options, self._session, raw_worklog_json) for raw_worklog_json in r_json['worklogs']]
return worklogs

@translate_resource_args
def worklog(self, issue, id):
"""
Get a specific worklog Resource from the server.
Expand All @@ -610,6 +647,7 @@ def worklog(self, issue, id):
"""
return self._find_for_resource(Worklog, (issue, id))

@translate_resource_args
def add_worklog(self, issue, timeSpent=None, adjustEstimate=None,
newEstimate=None, reduceBy=None):
"""
Expand Down Expand Up @@ -643,6 +681,7 @@ def add_worklog(self, issue, timeSpent=None, adjustEstimate=None,

### Issue links

@translate_resource_args
def create_issue_link(self, type, inwardIssue, outwardIssue, comment=None):
"""
Create a link between two issues.
Expand Down Expand Up @@ -768,6 +807,7 @@ def project(self, id):
return self._find_for_resource(Project, id)

# non-resource
@translate_resource_args
def project_avatars(self, project):
"""
Get a dict of all avatars for a project visible to the current authenticated user.
Expand All @@ -776,6 +816,7 @@ def project_avatars(self, project):
"""
return self._get_json('project/' + project + '/avatars')

@translate_resource_args
def create_temp_project_avatar(self, project, filename, size, avatar_img, contentType=None, auto_confirm=False):
"""
Register an image file as a project avatar. The avatar created is temporary and must be confirmed before it can
Expand Down Expand Up @@ -819,6 +860,7 @@ def create_temp_project_avatar(self, project, filename, size, avatar_img, conten
else:
return cropping_properties

@translate_resource_args
def confirm_project_avatar(self, project, cropping_properties):
"""
Confirm the temporary avatar image previously uploaded with the specified cropping.
Expand All @@ -838,6 +880,7 @@ def confirm_project_avatar(self, project, cropping_properties):

return json.loads(r.text)

@translate_resource_args
def set_project_avatar(self, project, avatar):
"""
Set a project's avatar.
Expand All @@ -847,6 +890,7 @@ def set_project_avatar(self, project, avatar):
"""
self._set_avatar(None, self._get_url('project/' + project + '/avatar'), avatar)

@translate_resource_args
def delete_project_avatar(self, project, avatar):
"""
Delete a project's avatar.
Expand All @@ -858,6 +902,7 @@ def delete_project_avatar(self, project, avatar):
r = self._session.delete(url)
self._raise_on_error(r)

@translate_resource_args
def project_components(self, project):
"""
Get a list of component Resources present on a project.
Expand All @@ -868,6 +913,7 @@ def project_components(self, project):
components = [Component(self._options, self._session, raw_comp_json) for raw_comp_json in r_json]
return components

@translate_resource_args
def project_versions(self, project):
"""
Get a list of version Resources present on a project.
Expand All @@ -879,6 +925,7 @@ def project_versions(self, project):
return versions

# non-resource
@translate_resource_args
def project_roles(self, project):
"""
Get a dict of role names to resource locations for a project.
Expand All @@ -887,6 +934,7 @@ def project_roles(self, project):
"""
return self._get_json('project/' + project + '/role')

@translate_resource_args
def project_role(self, project, id):
"""
Get a role Resource.
Expand Down Expand Up @@ -1176,6 +1224,7 @@ def search_allowed_users_for_issue(self, user, issueKey=None, projectKey=None, s

### Versions

@translate_resource_args
def create_version(self, name, project, description=None, releaseDate=None):
"""
Create a version in a project and return a Resource for it.
Expand Down
Loading

0 comments on commit dd67e66

Please sign in to comment.